Fission-AI/OpenSpec · error · RootSelectionError
Declared in
Error message
Declared in ${pointer.filePath}: ${error.message} What it means
A rewrapping boundary in resolveNearestOrDeclaredRoot: a store resolution triggered by a directory's declared store pointer failed, and the underlying RootSelectionError is re-thrown prefixed with the declaring file so the user knows the error originates from the pointer declaration, not from a --store flag. The unknown-store fix is reshaped to suggest registering the store or editing the pointer file.
Solutions
- Register the declared store: 'openspec store register <path> --id <declared-id>'
- Edit the pointer file named in the message to declare a store that is registered
- Delete the pointer file to fall back to nearest-root resolution
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at src/core/root-selection.ts:345 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Fission-AI/OpenSpec@6926ccb18a (2026-08-25).
Data as JSON: /api/errors/7b5dcdf9ddb2d0d3.
Report an issue: GitHub.
Appendix: source
Thrown at src/core/root-selection.ts:345
);
}
if (pointer.value === undefined) {
return makeRoot(nearestRoot, 'nearest');
}
try {
return await resolveStoreRoot(pointer.value, globalDataDir, 'declared');
} catch (error) {
if (error instanceof RootSelectionError) {
// Rewrap with the declaration origin. The unknown-store fix is
// reshaped for the actual mistake: the user declared a pointer,
// they did not pass --store.
const declarationFix =
error.diagnostic.code === 'unknown_store'
? `Register the store (openspec store register <path> --id ${pointer.value}) or edit ${pointer.filePath} to name a registered store.`
: error.diagnostic.fix;
throw new RootSelectionError(
`Declared in ${pointer.filePath}: ${error.message}`,
error.diagnostic.code,
{
...(error.diagnostic.target ? { target: error.diagnostic.target } : {}),
...(declarationFix ? { fix: declarationFix } : {}),
}
);
}
throw error;
}
}
/**
* The machine-level fallback: the global `defaultStore` resolved as a root,
* with its own provenance (`global_default`) so JSON surfaces can tell a
* machine-wide default from a repo's `store:` pointer. Mirrors the
* declared-pointer catch — a stale or unregistered id degrades to the
* underlying error, reshaped to point at clearing the global defaultView on GitHub (pinned to 6926ccb18a)