Fail soft on operations API domain socket bind failure; warn on path-length overflow#1907
Draft
kriszyp wants to merge 2 commits into
Draft
Fail soft on operations API domain socket bind failure; warn on path-length overflow#1907kriszyp wants to merge 2 commits into
kriszyp wants to merge 2 commits into
Conversation
A Unix domain socket path over ~107 bytes (Linux) fails at listen() time with EINVAL. server/threads/threadServer.js's listenOnPorts() wrapped every listener — domain socket and TCP alike — in one Promise.all(), so a single EINVAL rejected the whole batch and propagated out of startHTTPThreads(), which bin/run.ts's main() catches by calling process.exit(1) — killing the entire process over what should be a non-fatal loss of a convenience mirror. A long rootPath (e.g. any `.claude/worktrees/<name>` checkout, which this very fix was developed in) is enough on its own to trigger this with the operations API's default relative domain socket name. - threadServer.js: a domain socket listen failure now logs and resolves instead of rejecting, in both the Node and Bun listen loops, so the rest of the batch (TCP ports, other domain sockets) is unaffected. - configValidator.ts: adds getDomainSocketPathLengthWarning, which resolves operationsApi.network.domainSocket against rootPath and flags a byte length past the platform's sun_path limit. It's a plain function rather than a Joi schema rule, because Joi skips a field's own .custom() whenever the field's value came from .default() — exactly the common case here (domainSocket left unset). configUtils.ts calls it after validation and logs (non-blocking): a lost domain socket shouldn't refuse to start Harper the way a real config error does. Refs harper-1839-sql-selectall-pk-sort Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces a fail-soft mechanism for Unix domain socket binding errors during startup, preventing startup abortion when a domain socket path exceeds the platform's limit (103 bytes on macOS, 107 bytes on Linux). It adds path length validation warnings in configUtils.ts and configValidator.ts, along with corresponding unit tests. The reviewer suggests updating getDomainSocketPathLengthWarning to accept an optional platform parameter to facilitate robust, platform-independent unit testing of the path resolution logic on any CI host.
Contributor
|
Reviewed; no blockers found. |
Lets the Unix-socket path-length check be unit tested for darwin/linux/win32 resolution from any CI host, instead of only ever exercising process.platform's own branch. Defaults to process.platform so callers are unaffected. Addresses gemini-code-assist review feedback on PR #1907. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What / why
A Unix domain socket path over ~107 bytes (Linux) / ~103 bytes (macOS) fails at
listen()time withEINVAL.server/threads/threadServer.js'slistenOnPorts()wrapped every listener — the operations API's domain socket and its TCP port alike — in onePromise.all(), so a singleEINVALrejected the whole batch and propagated out ofstartHTTPThreads(), whichbin/run.ts'smain()catches by callingprocess.exit(1)— killing the entire Harper process over what should be a non-fatal loss of a convenience mirror.A long
rootPath(e.g. any.claude/worktrees/<name>checkout — this fix was developed in one) is enough on its own to trigger this with the operations API's default relative domain socket name (operations-server), with nothing in the default output explaining why.Changes
server/threads/threadServer.js: a domain socket listen failure now logs and resolves instead of rejecting, in both the Node and Bun listen loops, so the rest of the batch (TCP ports, other domain sockets) is unaffected.validation/configValidator.ts: addsgetDomainSocketPathLengthWarning, which resolvesoperationsApi.network.domainSocketagainstrootPathand flags a byte length past the platform'ssun_pathlimit. It's a plain function rather than a Joi schema rule, because Joi skips a field's own.custom()whenever that field's value came from.default()— exactly the common case here (domain socket left unset, onlyrootPathis long).config/configUtils.ts: calls the warning check after config validation and logs (non-blocking) — a lost domain socket shouldn't refuse to start Harper the way a real config error does; the TCP port is unaffected either way.Test notes
unitTests/server/threads/threadServerListenOnPorts.test.js(new): confirmslistenOnPorts()resolves rather than rejects when a domain socket listen fails, and that a sibling TCP listener in the same batch still comes up. Verified these fail against the pre-fix code (rejected with the simulatedEINVAL).unitTests/validation/configValidator.test.js: unit tests forgetDomainSocketPathLengthWarningcovering relative/absolute paths, the disabled (false) case, and the exact byte boundary.unitTests/config/configUtils.test.js: confirmsvalidateConfiglogs a warning (not a thrown error) when the resolved domain socket path is too long.test:unit:config,test:unit:validation-equivalent, and the affectedunitTests/server/**files locally — all green, no regressions.Risks / open questions
server/operationsServer.ts, which the originating finding cited — that file's try/catch aroundserverRegistration.http(...)never actually reaches the failinglisten()call (that happens later, on the main thread, inthreadServer.js'slistenOnPorts()), so no change was needed there.Generated with Claude Code (Sonnet 5).
🤖 Generated with Claude Code