(err: NodeJS.ErrnoException)
| 3137 | const tryListen = (attempt: number): Promise<void> => { |
| 3138 | return new Promise<void>((resolveAttempt, rejectAttempt) => { |
| 3139 | const onError = async (err: NodeJS.ErrnoException) => { |
| 3140 | server.removeListener("error", onError); |
| 3141 | |
| 3142 | if (err.code === "EADDRINUSE") { |
| 3143 | // Port is in use - check if a proxy is actually running |
| 3144 | const existingProxy2 = await checkExistingProxy(listenPort); |
| 3145 | if (existingProxy2) { |
| 3146 | // Proxy is actually running - this is fine, reuse it |
| 3147 | console.log(`[ClawRouter] Existing proxy detected on port ${listenPort}, reusing`); |
| 3148 | rejectAttempt({ |
| 3149 | code: "REUSE_EXISTING", |
| 3150 | wallet: existingProxy2.wallet, |
| 3151 | existingChain: existingProxy2.paymentChain, |
| 3152 | }); |
| 3153 | return; |
| 3154 | } |
| 3155 | |
| 3156 | // Port is in TIME_WAIT (no proxy responding) - retry after delay |
| 3157 | if (attempt < PORT_RETRY_ATTEMPTS) { |
| 3158 | console.log( |
| 3159 | `[ClawRouter] Port ${listenPort} in TIME_WAIT, retrying in ${PORT_RETRY_DELAY_MS}ms (attempt ${attempt}/${PORT_RETRY_ATTEMPTS})`, |
| 3160 | ); |
| 3161 | rejectAttempt({ code: "RETRY", attempt }); |
| 3162 | return; |
| 3163 | } |
| 3164 | |
| 3165 | // Max retries exceeded |
| 3166 | console.error( |
| 3167 | `[ClawRouter] Port ${listenPort} still in use after ${PORT_RETRY_ATTEMPTS} attempts`, |
| 3168 | ); |
| 3169 | rejectAttempt(err); |
| 3170 | return; |
| 3171 | } |
| 3172 | |
| 3173 | rejectAttempt(err); |
| 3174 | }; |
| 3175 | |
| 3176 | server.once("error", onError); |
| 3177 | server.listen(listenPort, "127.0.0.1", () => { |
nothing calls this directly
no test coverage detected