{"record":{"id":"9dfa85a71f0118f6","repo":"mastra-ai/mastra","slug":"not-a-git-repository-dir","errorCode":null,"errorMessage":"Not a git repository: ${dir}","messagePattern":"Not a git repository: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/git-history.ts","lineNumber":173,"sourceCode":"   * (e.g., the user commits or pulls).\n   */\n  invalidateCache(): void {\n    this.repoRootCache.clear();\n    this.commitCache.clear();\n    this.snapshotCache.clear();\n  }\n\n  // ===========================================================================\n  // Internals\n  // ===========================================================================\n\n  /**\n   * Get the relative path from the Git repo root to a file in the storage directory.\n   */\n  private relativeToRepo(dir: string, filename: string): string {\n    const root = this.repoRootCache.get(dir);\n    if (!root) {\n      throw new Error(`Not a git repository: ${dir}`);\n    }\n    // Resolve symlinks so that macOS /var → /private/var differences don't break relative()\n    const realRoot = realpathSync(root);\n    const realDir = realpathSync(dir);\n    const relDir = relative(realRoot, realDir);\n    return relDir ? `${relDir}/${filename}` : filename;\n  }\n\n  /**\n   * Execute a git command and return stdout.\n   */\n  private exec(cwd: string, args: string[]): Promise<string> {\n    return new Promise((resolve, reject) => {\n      execFile('git', args, { cwd, maxBuffer: 10 * 1024 * 1024 }, (error, stdout) => {\n        if (error) reject(error);\n        else resolve(stdout);\n      });\n    });","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/git-history.ts#L155-L191","documentation":"GitHistoryStorage resolves a file path relative to the discovered git repository root; relativeToRepo throws when no repo root was cached/resolved for the storage directory, meaning the directory is not inside a git work tree. The path-based storage cannot record history without git metadata.","triggerScenarios":"Instantiating the storage with a directory outside any git repository (or with git metadata missing); repoRootCache not populated because resolveRepoRoot failed for that dir; using a temp dir that was created without git init; calling relPath before initialization.","commonSituations":"Deployed containers running from a directory copied without the .git folder; tests writing to a bare tmpdir; monorepo where the storage dir sits above the git root.","solutions":["Run `git init` in (or move storage under) a directory inside a git work tree.","Ensure the .git directory is present in deployments (don't strip it from the build artifact).","Configure the storage to point at a path inside the existing repository root."],"exampleFix":"// before\nconst storage = new FilesystemVersionedStorage({ dir: '/tmp/cache' }); // no git\n// after\nmkdirSync(dir, { recursive: true });\nexecSync('git init', { cwd: dir });\nconst storage = new FilesystemVersionedStorage({ dir });","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\nif (!existsSync(`${dir}/.git`)) {\n  execSync(`git init ${dir}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await storage.list(...);\n} catch (e) {\n  if (String(e.message).startsWith('Not a git repository')) {\n    execSync(`git init ${storageDir}`); // then retry\n  } else throw e;\n}","preventionTips":["Ensure the storage directory lives inside a git work tree; keep .git in deployed artifacts.","Run `git init` during bootstrap of ephemeral/test storage directories.","Don't copy storage dirs without their .git folder between environments."],"tags":["git","filesystem","configuration"],"backgroundTag":"not-a-git-repository","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}