{"record":{"id":"ac3e24413330a2fe","repo":"can1357/oh-my-pi","slug":"no-artifacts-directory-found","errorCode":null,"errorMessage":"No artifacts directory found","messagePattern":"No artifacts directory found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/agent-protocol.ts","lineNumber":91,"sourceCode":"\t\t// separator: `agent://Parent/Child` resolves `Parent.Child.md`. Only when\n\t\t// no such nested output exists does the path fall back to jq-style JSON\n\t\t// extraction on `<outputId>.md`. Query form (`?q=`) is always extraction.\n\t\tconst pathSegments = hasPathExtraction ? urlPath.split(\"/\").filter(Boolean) : [];\n\t\tconst decodedSegments = pathSegments.map(segment => {\n\t\t\ttry {\n\t\t\t\treturn decodeURIComponent(segment);\n\t\t\t} catch {\n\t\t\t\treturn segment;\n\t\t\t}\n\t\t});\n\t\tconst nestedId =\n\t\t\tdecodedSegments.length > 0 && decodedSegments.every(segment => !segment.includes(\".\"))\n\t\t\t\t? [outputId, ...decodedSegments].join(\".\")\n\t\t\t\t: undefined;\n\n\t\tconst scan = await this.#findOutput(dirs, nestedId ? [nestedId, outputId] : [outputId]);\n\t\tif (!scan.anyDirExists) {\n\t\t\tthrow new Error(\"No artifacts directory found\");\n\t\t}\n\t\tif (!scan.foundPath) {\n\t\t\tconst target = nestedId ?? outputId;\n\t\t\tconst availableStr = scan.availableIds.size > 0 ? [...scan.availableIds].join(\", \") : \"none\";\n\t\t\tthrow new Error(`Not found: ${target}\\nAvailable: ${availableStr}`);\n\t\t}\n\n\t\tconst rawContent = await Bun.file(scan.foundPath).text();\n\t\tconst notes: string[] = [];\n\t\tlet content = rawContent;\n\t\tlet contentType: InternalResource[\"contentType\"] = \"text/markdown\";\n\n\t\t// Extraction applies only when the URL did NOT resolve to a nested output\n\t\t// (a slash that named a real child is a hierarchy hop, not a jq path).\n\t\tconst extract = hasQueryExtraction || (hasPathExtraction && scan.matchedId !== nestedId);\n\t\tif (extract) {\n\t\t\tlet jsonValue: unknown;\n\t\t\ttry {","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/agent-protocol.ts#L73-L109","documentation":"After gathering the candidate artifacts directories, #findOutput() reports whether any of them actually exists on disk (anyDirExists). If none exist (all readdir calls hit ENOENT), the handler throws 'No artifacts directory found'. Distinct from error 1502: the registry produced directory paths, but none of them exist on the filesystem.","triggerScenarios":"artifactsDirsFromRegistry() returns one or more dir paths but every one of them is missing on disk — e.g. resolving agent://<id> after session artifacts were deleted, or with a preferredDir derived from a sessionFile whose sibling artifacts dir was never created.","commonSituations":"Pointing at a session file whose artifacts dir was removed or never written (fresh session with no outputs yet); stale registry entries pointing at cleaned-up temp directories; running in an environment where the session storage path was wiped (container restart, rm -rf of session dir).","solutions":["Confirm the artifacts directory for the current session exists (session file path minus '.jsonl')","Run an agent to produce at least one output so the artifacts dir is created","If dirs were deleted intentionally, re-register a fresh session before resolving agent:// URLs"],"exampleFix":"// before\nconst res = await handler.resolve(parseUrl(\"agent://out1\"), { sessionFile: deletedSession });\n// after\n// ensure the artifacts dir exists or use a session whose artifacts dir is present\nconst res = await handler.resolve(parseUrl(\"agent://out1\"), { sessionFile: liveSession });","handlingStrategy":"fallback","validationCode":"import { existsSync } from \"node:fs\";\nconst dirs = artifactsDirsFromRegistry();\nif (!dirs.some(d => existsSync(d))) {\n  // artifacts dirs are gone; re-run an agent to recreate them\n}","typeGuard":null,"tryCatchPattern":"try {\n  const resource = await handler.resolve(url, context);\n} catch (err) {\n  if (err instanceof Error && err.message === \"No artifacts directory found\") {\n    // fall back: regenerate the output or surface 'artifacts unavailable'\n  } else throw err;\n}","preventionTips":["Do not delete session artifacts dirs while sessions are registered","Verify the session storage path is intact after environment restarts","Create at least one agent output before attempting agent:// resolution"],"tags":["filesystem","session","missing-directory","agent-protocol"],"backgroundTag":"missing-directory","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}