mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 16:02:03 +00:00
fix(repos): recognise underscore errno families, and route runtime errors safely
Final review found the errno-shape rule still failed open. `/^E[A-Z0-9]+$/` misses `EAI_AGAIN` and `EAI_NONAME` — real libuv codes this repo already treats as transient in ssh-connection-utils. A DNS/transport failure whose message quotes ENOENT therefore skipped the code arm, matched the message, and read as proven absence: the `.git` probe would continue into `git init` on a transient fault, in all three lanes. Underscores are now allowed. The consequence is that an unrecognised E-prefixed code counts as an errno and so is NOT absence — it biases toward refusing, which is the safe direction here and is now stated in the comment rather than implied. Only a code that is not errno-shaped at all (a domain string, or the relay's numeric -32000) falls through to the message. The runtime lane also still formatted its probe failure with `error.message` directly, so a throwing getter could escape the refusal. It uses describeError, matching the other two lanes.
This commit is contained in:
@@ -111,4 +111,16 @@ describe('proven-absence', () => {
|
||||
})
|
||||
expect(() => describeError(e)).not.toThrow()
|
||||
})
|
||||
|
||||
it('treats underscore errno families like EAI_* as authoritative', () => {
|
||||
// EAI_AGAIN is a real libuv code; missing it let a transient DNS failure whose message
|
||||
// quotes ENOENT read as proven absence.
|
||||
for (const code of ['EAI_AGAIN', 'EAI_NONAME']) {
|
||||
expect(
|
||||
isProvenAbsent(
|
||||
Object.assign(new Error("ENOENT: no such file or directory, stat '/x'"), { code })
|
||||
)
|
||||
).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -7,9 +7,14 @@ const ENOTDIR_MESSAGE = /^ENOTDIR: not a directory\b/
|
||||
|
||||
// Why shape rather than a fixed list: EVERY real errno is authoritative, not just the two we care
|
||||
// about — an EACCES or ELOOP is a definitive non-absence answer even when the message quotes
|
||||
// ENOENT. But a wrapper attaching a domain string (`REMOTE_FS_ERROR`) is not an errno and must not
|
||||
// suppress the message fallback, which is the only classification path over the SSH relay.
|
||||
const ERRNO_NAME = /^E[A-Z0-9]+$/
|
||||
// ENOENT. Underscores are required: `EAI_AGAIN`/`EAI_NONAME` are real libuv codes, and missing them
|
||||
// let a transient DNS failure fall through to the message and read as proven absence.
|
||||
//
|
||||
// An E-prefixed code we do not recognise is therefore treated as an errno, i.e. NOT absence. That
|
||||
// biases toward refusing, which is the safe direction for this helper. Only a code that is not
|
||||
// errno-shaped at all (`REMOTE_FS_ERROR`, or the relay's numeric -32000) falls through to the
|
||||
// message — the only classification path that survives the SSH relay.
|
||||
const ERRNO_NAME = /^E[A-Z0-9_]+$/
|
||||
|
||||
/** Whether a failed probe proves the path is absent. Never throws. */
|
||||
export function isProvenAbsent(error: unknown): boolean {
|
||||
|
||||
@@ -1278,7 +1278,7 @@ import {
|
||||
LEFTOVER_GIT_DIR_RETRY_HINT,
|
||||
repositoryCheckUnavailableError
|
||||
} from '../ipc/repos/repository-creation-messages'
|
||||
import { isProvenAbsent } from '../ipc/repos/proven-absence'
|
||||
import { describeError, isProvenAbsent } from '../ipc/repos/proven-absence'
|
||||
import { getWorktreeWatcherRemoval } from '../ipc/worktree-watcher-removal'
|
||||
import { acquireWatcherRemovalGate } from '../ipc/watcher-removal-gate'
|
||||
import {
|
||||
@@ -23925,7 +23925,7 @@ export class OrcaRuntimeService {
|
||||
// as "no failure" and fail open into `git init`.
|
||||
if (!isProvenAbsent(error)) {
|
||||
gitProbeFailed = true
|
||||
gitProbeFailure = error instanceof Error ? error.message : String(error)
|
||||
gitProbeFailure = describeError(error)
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user