{"record":{"id":"5168a343e4576cb3","repo":"garrytan/gstack","slug":"cannot-resolve-real-path-filepath-err-code","errorCode":null,"errorMessage":"Cannot resolve real path: ${filePath} (${err.code})","messagePattern":"Cannot resolve real path: (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/path-security.ts","lineNumber":92,"sourceCode":"  }\n}\n\n/** Validate a file path for reading (eval command). */\nexport function validateReadPath(filePath: string): void {\n  const resolved = path.resolve(filePath);\n  let realPath: string;\n  try {\n    realPath = fs.realpathSync(resolved);\n  } catch (err: any) {\n    if (err.code === 'ENOENT') {\n      try {\n        const dir = fs.realpathSync(path.dirname(resolved));\n        realPath = path.join(dir, path.basename(resolved));\n      } catch {\n        realPath = resolved;\n      }\n    } else {\n      throw new Error(`Cannot resolve real path: ${filePath} (${err.code})`);\n    }\n  }\n  const isSafe = SAFE_DIRECTORIES.some(dir => isPathWithin(realPath, dir));\n  if (!isSafe) {\n    throw new Error(`Path must be within: ${SAFE_DIRECTORIES.join(', ')}`);\n  }\n}\n\n/** Validate a file path for remote serving (GET /file). TEMP_DIR only, not cwd. */\nexport function validateTempPath(filePath: string): void {\n  const resolved = path.resolve(filePath);\n  let realPath: string;\n  try {\n    realPath = fs.realpathSync(resolved);\n  } catch (err: any) {\n    if (err.code === 'ENOENT') {\n      throw new Error('File not found');\n    }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/path-security.ts#L74-L110","documentation":"Thrown by validateReadPath when realpathSync fails with an errno other than ENOENT. ENOENT is handled separately (file does not exist yet, fall back to parent-dir check); any other failure — EACCES (permission denied), ELOOP (circular symlink), ENOTDIR (a path component is not a directory) — surfaces here with the raw errno code.","triggerScenarios":"Calling eval with a file path that hits a permission wall, a symlink loop, or a non-directory component. realpathSync throws and err.code is not 'ENOENT', so the original cause is re-exposed with its errno.","commonSituations":"File owned by another user with no read permission on the browse process; symlink loop created by misconfigured dotfiles; a regular file sitting where a directory was expected in the path; SELinux/AppArmor denial.","solutions":["Inspect permissions: `ls -la <path>` and `namei -l <path>` to see per-component perms","chmod/chown the file or run the browse process as an authorized user","Break symlink loops: `readlink -f <path>` to find the cycle, then remove the offending link","Ensure every component except the last is a directory"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import * as fs from 'fs';\n\nfunction canReadResolved(p: string): boolean {\n  try {\n    fs.realpathSync(p);\n    fs.accessSync(p, fs.constants.R_OK);\n    return true;\n  } catch (e: any) {\n    if (e.code === 'ENOENT') return true; // non-existent is fine for read validation\n    return false; // EACCES, ELOOP, ENOTDIR, etc.\n  }\n}\n\nif (!canReadResolved(filePath)) {\n  throw new Error(`Cannot read ${filePath}: fix permissions or symlink loops first`);\n}","typeGuard":"function isResolvableRealpath(p: string): boolean {\n  try { fs.realpathSync(p); return true; }\n  catch (e: any) { return e.code === 'ENOENT'; }\n}","tryCatchPattern":"try {\n  await runReadCommand(filePath);\n} catch (e: any) {\n  if (/Cannot resolve real path/.test(e.message)) {\n    const m = e.message.match(/\\((\\w+)\\)$/);\n    const code = m?.[1];\n    if (code === 'EACCES') console.error('Permission denied — chmod/chown the file or run as an authorized user.');\n    else if (code === 'ELOOP') console.error('Circular symlink — remove the loop with readlink -f.');\n    else if (code === 'ENOTDIR') console.error('A path component is not a directory.');\n  }\n  throw e;\n}","preventionTips":["Check fs.accessSync(p, R_OK) before passing a path to eval","Avoid symlink loops in dotfiles and test fixtures","Run the browse process as a user with read access to the files it needs","Use readlink -f to verify the real path is reachable before the command"],"tags":["filesystem","permissions","symlink","errno","eacces","eloop"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}