{"record":{"id":"fe365b709f1f18d1","repo":"coleam00/Archon","slug":"failed-to-read-version-err-message","errorCode":null,"errorMessage":"Failed to read version: ${err.message}","messagePattern":"Failed to read version: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/version.ts","lineNumber":46,"sourceCode":"\n/**\n * Get version for development mode (reads package.json)\n */\nasync function getDevVersion(): Promise<{ name: string; version: string }> {\n  // Read root package.json (monorepo version), not the CLI package's own\n  const pkgPath = join(SCRIPT_DIR, '../../../../package.json');\n\n  let content: string;\n  try {\n    content = await readFile(pkgPath, 'utf-8');\n  } catch (error) {\n    const err = error as NodeJS.ErrnoException;\n    if (err.code === 'ENOENT') {\n      throw new Error('Failed to read version: package.json not found (bad installation?)');\n    } else if (err.code === 'EACCES') {\n      throw new Error('Failed to read version: permission denied reading package.json');\n    }\n    throw new Error(`Failed to read version: ${err.message}`);\n  }\n\n  let pkg: PackageJson;\n  try {\n    pkg = JSON.parse(content) as PackageJson;\n  } catch (_error) {\n    throw new Error('Failed to read version: package.json is malformed');\n  }\n\n  return { name: pkg.name, version: pkg.version };\n}\n\n/**\n * Get the git commit hash at runtime (dev mode).\n * Returns 'unknown' if git is unavailable or the command fails.\n */\nasync function getDevGitCommit(): Promise<string> {\n  try {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/cli/src/commands/version.ts#L28-L64","documentation":"getDevVersion's catch-all: after the specialized ENOENT and EACCES branches, any other readFile failure is rethrown with the original Node error message prefixed with 'Failed to read version:'. It preserves the underlying evidence (e.g. EISDIR, ELOOP, EMFILE) while giving it version-command context.","triggerScenarios":"devInfo -> getDevVersion calls readFile(pkgPath) and Node rejects with an errno other than ENOENT/EACCES: EISDIR (a directory named package.json exists), ELOOP (symlink loop), EMFILE/ENFILE (fd exhaustion), EIO (disk error), or an fs layer intercepting the read (e.g. broken FUSE mount).","commonSituations":"A directory accidentally created named package.json in the install root; a dangling symlink chain in the install path; too many open files from a long-running shell; NFS/FUSE mount failure on a networked install directory.","solutions":["Read the wrapped err.message to identify the errno (EISDIR, ELOOP, EMFILE...) and fix that specific condition.","If EISDIR: remove/rename the directory that is occupying the package.json path and restore the real file via reinstall.","If ELOOP: repair the symlink chain in the install path (reinstall is simplest).","If EMFILE/ENFILE: raise the fd limit (`ulimit -n`) or close leaking processes, then retry."],"exampleFix":"// before\n$ ls -la /opt/archon/lib/package.json\ndrwxr-xr-x 2 user user 4096 package.json   # directory shadowing the file -> EISDIR\n// after\n$ rm -r /opt/archon/lib/package.json && bun install -g @archon/cli   # reinstall restores the real file","handlingStrategy":"try-catch","validationCode":"import { lstatSync } from 'node:fs';\nconst st = lstatSync(pkgPath, { throwIfNoEntry: false });\nif (st?.isDirectory()) {\n  throw new Error(`${pkgPath} is a directory (EISDIR): remove it and reinstall to restore the real package.json`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const info = await devInfo();\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Failed to read version:') && !err.message.includes('not found') && !err.message.includes('permission denied')) {\n    // err.message carries the raw errno (EISDIR/ELOOP/EMFILE...);\n    // fix that specific OS condition, most often via reinstall.\n  } else throw err;\n}","preventionTips":["Don't create files/directories named package.json in install roots by accident (scripts, tab-completion).","Repair or avoid symlink loops in install paths; reinstall is the reliable reset.","Raise ulimit -n on machines running many file handles alongside the CLI.","Watch for networked/FUSE mounts hosting the install going stale."],"tags":["filesystem","readfile","errno","version"],"backgroundTag":"filesystem-read-error","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}