{"record":{"id":"af94d88fb5900111","repo":"abhigyanpatwari/GitNexus","slug":"source-branch-name-contains-characters-not-all","errorCode":null,"errorMessage":"${source}: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \\).","messagePattern":"(.+?): branch name contains characters not allowed in a git ref \\(~ \\^ : \\? \\* \\[ \\\\\\)\\.","errorType":"validation","errorClass":"GitNexusRcError","httpStatus":null,"severity":"warning","filePath":"gitnexus/src/cli/analyze-config.ts","lineNumber":177,"sourceCode":" * Validate a user-supplied branch name (from CLI or `.gitnexusrc`). Returns the\n * trimmed name or throws {@link GitNexusRcError}. Conservative but accepts the\n * shapes real branches use (`feature/foo-bar`, `release/1.2`, `develop`).\n */\nexport function validateBranchName(value: string, source: string): string {\n  const trimmed = value.trim();\n  if (!trimmed) {\n    throw new GitNexusRcError(`${source}: branch name must not be empty.`);\n  }\n  if (trimmed.length > BRANCH_MAX_LENGTH) {\n    throw new GitNexusRcError(`${source}: branch name is too long (max ${BRANCH_MAX_LENGTH}).`);\n  }\n  assertNoHiddenChars(trimmed, source);\n  if (/\\s/.test(trimmed)) {\n    throw new GitNexusRcError(`${source}: branch name must not contain whitespace.`);\n  }\n  // git ref-name rules (subset): reject characters git itself forbids in refs.\n  if (/[~^:?*[\\\\]/.test(trimmed)) {\n    throw new GitNexusRcError(\n      `${source}: branch name contains characters not allowed in a git ref (~ ^ : ? * [ \\\\).`,\n    );\n  }\n  if (trimmed.startsWith('-')) {\n    throw new GitNexusRcError(`${source}: branch name must not start with \"-\".`);\n  }\n  if (trimmed.includes('..')) {\n    throw new GitNexusRcError(`${source}: branch name must not contain \"..\".`);\n  }\n  // Git permits a backtick in a ref, but the branch is embedded inside a\n  // Markdown inline-code span in the generated AGENTS.md/CLAUDE.md regression\n  // example, where a backtick would close the span early and let the rest of\n  // the template render as instruction text. Reject it at this single\n  // chokepoint so all three tiers (CLI flag, .gitnexusrc, auto-detect via\n  // sanitizeDetectedBranch) are covered (#1996 tri-review P1).\n  if (trimmed.includes('`')) {\n    throw new GitNexusRcError(\n      `${source}: branch name must not contain a backtick (it would break the generated Markdown).`,","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/52924ef12c2290ceee4612526a828ec4cdf2047f/gitnexus/src/cli/analyze-config.ts#L159-L195","documentation":"During a wipe of the DB directory, the contentless `.lock` file survived all unlink retries (HANDLE_RELEASE_PROBE_ATTEMPTS with backoff). The wipe deliberately continues because the lock carries no state and initLbug recreates it; a genuinely held lock will instead surface as the reopen's own lock-busy error. Only surviving data files (dataSurvivors) escalate to LbugWipeError.","triggerScenarios":"survivors after the retry loop includes lockPath on Windows or any platform where unlink of the lock is deferred — AV or another process transiently holding the lock file during a wipe-and-reopen flow.","commonSituations":"Reindex flows that wipe the storage directory; a second GitNexus process or file scanner touching the lock at wipe time; Windows filter drivers deferring deletion. The subsequent open either succeeds (lock was stale) or fails with a lock-busy error that names the real holder.","solutions":["No action if the subsequent reopen succeeds — the warn documents a deliberate continuation","If reopen fails with lock-busy, find the concurrent process holding the lock and stop it","Keep AV exclusions on the storage directory so unlink retries succeed","Ensure only one wipe/reindex runs against the storage dir at a time"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":"import { LbugWipeError } from 'gitnexus/dist/core/lbug/lbug-adapter.js';\nconst isLbugWipeError = (e: unknown): e is LbugWipeError => e instanceof LbugWipeError;","tryCatchPattern":"try {\n  await wipeLbugDirectory(dbPath);\n} catch (e) {\n  if (isLbugWipeError(e)) {\n    // data files survived (the .lock alone never fails the wipe):\n    // stop whatever holds them, then retry the wipe once\n    logger.warn(`wipe survivors: ${e.survivors?.join(', ')}`);\n    throw e;\n  }\n  throw e;\n}","preventionTips":["Expect the lock-file warn to be non-fatal by design — only LbugWipeError (data survivors) matters","Close all DB users before wiping the storage directory","AV exclusions reduce unlink-retry survivors on Windows"],"tags":["ladybugdb","lock-file","wipe"],"backgroundTag":"stale-lock-file","analyzedSha":"52924ef12c2290ceee4612526a828ec4cdf2047f","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}