{"record":{"id":"5f1afd3e69bb2ec3","repo":"nexu-io/open-design","slug":"project-files-read-json-only-supports-json-files","errorCode":null,"errorMessage":"project_files.read_json only supports .json files","messagePattern":"project_files\\.read_json only supports \\.json files","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/daemon/src/live-artifacts/refresh.ts","lineNumber":588,"sourceCode":"    if (!matched) continue;\n    const result: BoundedJsonObject = {\n      path: file.path,\n      name: file.name,\n      size: file.size,\n      mtime: file.mtime,\n      kind: file.kind ?? 'file',\n      mime: file.mime ?? 'application/octet-stream',\n    };\n    if (preview !== undefined) result.preview = preview;\n    matches.push(result);\n  }\n\n  return asBoundedRefreshOutput({ toolName: 'project_files.search', query: query ?? '', count: matches.length, truncated: allFiles.length > matches.length && matches.length >= maxResults, matches });\n}\n\nasync function executeProjectFilesReadJson(options: ExecuteLocalDaemonRefreshSourceOptions): Promise<BoundedJsonObject> {\n  const filePath = selectJsonPath(options.source.input as ProjectFilesReadJsonInput);\n  if (!filePath.endsWith('.json')) throw new Error('project_files.read_json only supports .json files');\n  const dir = projectDir(options.projectsRoot, options.projectId);\n  const target = path.resolve(dir, filePath);\n  const [dirReal, targetLinkStat] = await Promise.all([realpath(dir), lstat(target)]);\n  if (targetLinkStat.isSymbolicLink()) throw new Error('project_files.read_json does not follow symlinks');\n  const targetReal = await realpath(target);\n  if (!targetReal.startsWith(`${dirReal}${path.sep}`) && targetReal !== dirReal) {\n    throw new Error('project_files.read_json path escapes project dir');\n  }\n  const entryStat = await stat(targetReal);\n  if (!entryStat.isFile()) throw new Error('project_files.read_json path must be a file');\n  if (entryStat.size > 256 * 1024) throw new Error('project_files.read_json file exceeds 256KB');\n  if (options.signal?.aborted === true) throw options.signal.reason;\n  let parsed: BoundedJsonValue;\n  try {\n    parsed = JSON.parse(await readFile(targetReal, 'utf8')) as BoundedJsonValue;\n  } catch {\n    throw new Error(`project_files.read_json could not parse JSON at ${filePath}`);\n  }","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/live-artifacts/refresh.ts#L570-L606","documentation":"executeProjectFilesReadJson (refresh.ts:587-588) requires the resolved file path to end with '.json'. This bounds the tool to JSON parsing only (it immediately JSON.parse's the contents), so non-JSON files are rejected before any filesystem traversal.","triggerScenarios":"input.path (or file/name) resolves to a path whose final extension is not '.json', e.g. 'data.txt', 'config.yaml', 'package.jsonc'.","commonSituations":"Pointing the read_json tool at a JSONC/YAML/TXT file by mistake; a path with no extension; a case-sensitivity issue such as '.JSON' (the check is case-sensitive on lowercased extension only via endsWith).","solutions":["Use a '.json' file path (lowercase).","If your data is JSONC/JSON5/YAML, convert it to plain JSON first, or use a different source type.","Rename or copy the file with a .json extension if its contents are valid JSON."],"exampleFix":"// before\nconst input = { path: 'config.yaml' };\n// throws `project_files.read_json only supports .json files`\n\n// after\nconst input = { path: 'config.json' };","handlingStrategy":"validation","validationCode":"function assertJsonFilePath(p: string): void {\n  if (!p.toLowerCase().endsWith('.json')) {\n    throw new Error('project_files.read_json only supports .json files');\n  }\n}","typeGuard":"function isJsonFilePath(p: unknown): p is string {\n  return typeof p === 'string' && p.toLowerCase().endsWith('.json');\n}","tryCatchPattern":null,"preventionTips":["Restrict the path picker UI to .json files for read_json sources.","Reject non-.json extensions at the input boundary with a clear message.","For JSONC/JSON5, convert to plain JSON before exposing to read_json."],"tags":["live-artifacts","project-files","file-extension"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}