abhigyanpatwari/GitNexus · warning
[group/sync] manifest link ${link.type}:${link.contract} ref
Error message
[group/sync] manifest link ${link.type}:${link.contract} references repos not in config.repos: ${dangling.join(', ')} — cross-links will use synthetic UIDs What it means
During group sync, a manifest-declared link (link.type:link.contract) has from/to endpoints that are not in knownRepos — the set of repos that actually initialized and hold a pool handle, not merely everything listed in config.repos. Cross-links for those endpoints fall back to synthetic UIDs, so they cannot be traced to real indexed symbols.
Source
Thrown at gitnexus/src/core/group/sync.ts:318
if (opts?.verbose) {
for (const s of wsResult.stats) {
logger.info(
` workspace-deps: discovered ${s.linkCount} cross-${s.ecosystem.toLowerCase()} links from ${s.projectCount} ${s.ecosystem} projects`,
);
}
}
}
}
if (allLinks.length > 0) {
// knownRepos = repos that actually initialized (have a pool handle), NOT
// every config.repos entry — a missing/failed repo has no handle, and
// intersecting against config keys would try to initLbug an undefined path.
const knownRepos = new Set(repoHandles.keys());
for (const link of allLinks) {
const dangling = [link.from, link.to].filter((r) => !knownRepos.has(r));
if (dangling.length > 0) {
logger.warn(
`[group/sync] manifest link ${link.type}:${link.contract} references repos not in config.repos: ${dangling.join(', ')} — cross-links will use synthetic UIDs`,
);
}
}
const manifestEx = new ManifestExtractor();
const windows = partitionManifestWindows(allLinks, knownRepos, getMaxResidentRepos());
// Resolve one window at a time: re-init + lease only the window's repos,
// resolve its links, then RELEASE (not close) the leases. Released repos
// become evictable and the pool's LRU reclaims them — bounding peak
// residency to ≤ getMaxResidentRepos() distinct repos per window while
// avoiding teardown of an entry a concurrent MCP reader may share
// (PR #2191 review, Findings 1 & 3).
for (const window of windows) {
const windowReleases: Array<() => void> = [];
try {
const windowExecutors = new Map<string, CypherExecutor>();View on GitHub (pinned to aac7515d2a)
Solutions
- Add the missing repo(s) named in the message to the group's config.repos with correct paths
- Fix why the repo failed to initialize (path, missing clone, permissions) so it gains a pool handle
- Remove or update stale link entries referencing repos no longer in the group
- Re-run group sync and confirm cross-links use real symbol UIDs
Example fix
# before — group config repos = ["api", "web"] # links manifest references "mobile" (not configured) # after — add the repo or drop the link repos = ["api", "web", "mobile"]
Defensive patterns
Strategy: validation
Validate before calling
// Validate before sync: every link endpoint must be a configured repo
const configured = new Set(groupConfig.repos); // config.repos entries
const dangling = allLinks.flatMap((link) =>
[link.from, link.to].filter((repo) => !configured.has(repo)),
);
if (dangling.length > 0) {
throw new Error(
`links reference unconfigured repos: ${[...new Set(dangling)].join(', ')} — ` +
`add them to config.repos or remove the links`,
);
} Type guard
function linkEndpointsConfigured(link: { from: string; to: string }, configured: ReadonlySet<string>): boolean {
return configured.has(link.from) && configured.has(link.to);
} Prevention
- Keep the links manifest in lockstep with config.repos — update links whenever a repo is added, removed, or renamed
- Validate repo paths and permissions before sync so every configured repo actually initializes and gains a pool handle
- Add a pre-sync lint that fails on any link endpoint not present in config.repos
When it happens
Trigger: A repo referenced by a link was removed from (or never added to) config.repos, or its initialization failed (bad path, permissions) so it never gained a pool handle; the message names the exact dangling endpoints.
Common situations: Removing or renaming a group repo without updating the links manifest; typos in repo names in link declarations; a repo whose path fails to init during sync (clone missing, permissions).
Related errors
- ${source} entries must all be strings.
- ${source} entries must not be empty.
- ${source} entry "${trimmed}" must be an identifier or member
- ${source} must list at least one string.
- ${source} must be a finite number.
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/59b70d930d45bc93.
Report an issue: GitHub.