can1357/oh-my-pi · error
artifact:// URL requires a numeric ID: artifact://0
Error message
artifact:// URL requires a numeric ID: artifact://0
What it means
parseArtifactId (packages/coding-agent/src/internal-urls/artifact-protocol.ts:30) throws when an artifact:// URL has an empty host, meaning no artifact ID was supplied. Artifact IDs are per-session numeric counters (e.g. artifact://0, artifact://3), so an ID is mandatory. The message embeds the offending URL form for clarity.
Source
Thrown at packages/coding-agent/src/internal-urls/artifact-protocol.ts:30
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { isEnoent } from "@oh-my-pi/pi-utils";
import { artifactsDirsFromRegistry } from "./registry-helpers";
import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
const MAX_INLINE_ARTIFACT_BYTES = 8 * 1024 * 1024;
/** Filesystem location for a session artifact, resolved without materializing its content. */
export interface ResolvedArtifactFile {
id: string;
path: string;
size: number;
}
function parseArtifactId(url: InternalUrl): string {
const id = url.rawHost || url.hostname;
if (!id) {
throw new Error("artifact:// URL requires a numeric ID: artifact://0");
}
if (!/^\d+$/.test(id)) {
throw new Error(`artifact:// ID must be numeric, got: ${id}`);
}
return id;
}
/** Resolve an `artifact://` URL to its backing file without reading artifact bytes. */
export async function resolveArtifactFile(url: InternalUrl, context?: ResolveContext): Promise<ResolvedArtifactFile> {
const id = parseArtifactId(url);
// Artifact ids are per-session counters; in multi-session hosts the same
// id exists in several dirs. Pin resolution to the calling session's
// artifacts dir first so `artifact://3` means *this* session's #3.
const dirs = artifactsDirsFromRegistry();
const pinnedDir = context?.localProtocolOptions?.getArtifactsDir?.() ?? null;
if (pinnedDir) {
const pinnedIndex = dirs.indexOf(pinnedDir);View on GitHub (pinned to 9690622007)
Solutions
- Supply the numeric artifact ID in the URL host: artifact://0, artifact://3, etc.
- List available IDs first (ArtifactProtocolHandler.complete, or directory listing of the session artifacts dir with files named <id>.<ext>) and pick a valid one.
- Fix the interpolation site so the ID variable is defined before building the URL.
- If you meant file content rather than an artifact, use a different scheme (e.g. file:// or agent://).
Example fix
// before
const url = `artifact://${id}`; // id === undefined -> artifact://
// after
if (id === undefined || id === null) throw new Error("artifact ID required");
const url = `artifact://${id}`; Defensive patterns
Strategy: validation
Validate before calling
if (!id || typeof id !== "string" || id.trim() === "") {
throw new Error("artifact URL requires a numeric ID");
}
const url = new URL(`artifact://${id}`); Type guard
function hasArtifactId(id: string | undefined | null): id is string {
return typeof id === "string" && id.length > 0;
} Try / catch
try {
const res = await resolveUrl(new URL(`artifact://${id}`));
} catch (err) {
if (err instanceof Error && err.message.includes("requires a numeric ID")) {
// id was empty; prompt user or list available IDs via completion
} else throw err;
} Prevention
- Never interpolate an ID variable into artifact:// without a defined check first.
- Validate ID presence and numeric shape at the string level before URL construction.
- List available artifact IDs before referencing one.
- Keep the scheme/ID pairing explicit in tool-call templates for agents.
When it happens
Trigger: Resolving the bare URL artifact:// (no host), e.g. new URL("artifact://") or a tool expanding an empty/undefined ID into the scheme; also artifact:/// (empty host with a leading slash path).
Common situations: Template interpolation with an undefined/null variable: `artifact://${id}` with id undefined; a script stripping the ID when slicing a longer URL string; an LLM emitting artifact:// without an ID in a tool call.
Related errors
- artifact:// ID must be numeric, got: ${id}
- No session - artifacts unavailable
- No artifacts directory found
- Invalid xd:// URL: ${url.href}. Use xd://<tool>.
- missing {name}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/124c613d05b3fd9e.
Report an issue: GitHub.