can1357/oh-my-pi · error
artifact:// ID must be numeric, got: ${id}
Error message
artifact:// ID must be numeric, got: ${id} What it means
parseArtifactId (packages/coding-agent/src/internal-urls/artifact-protocol.ts:33) throws when the artifact:// host is present but fails the /^\d+$/ numeric check. Artifact IDs are monotonically increasing counters, so only digits are accepted; named or alphanumeric hosts belong to other schemes like agent://<name>.
Source
Thrown at packages/coding-agent/src/internal-urls/artifact-protocol.ts:33
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);
if (pinnedIndex >= 0) dirs.splice(pinnedIndex, 1);
dirs.unshift(pinnedDir);
}View on GitHub (pinned to 9690622007)
Solutions
- Use a purely numeric ID: artifact://<digits>.
- If the target is a named agent output (e.g. reviewer_0), switch to the agent:// scheme: agent://reviewer_0.
- Strip file extensions/whitespace from the ID before building the URL.
- Check completion output (available IDs are numeric strings) to pick a valid ID.
Example fix
// before
const url = `artifact://${outputId}`; // outputId = "reviewer_0"
// after
const scheme = /^\d+$/.test(outputId) ? "artifact" : "agent";
const url = `${scheme}://${outputId}`; Defensive patterns
Strategy: validation
Validate before calling
if (!/^\d+$/.test(id)) {
throw new Error(`artifact:// requires a numeric ID, got: ${id}`);
}
const url = new URL(`artifact://${id}`); Type guard
function isNumericArtifactId(id: string): boolean {
return /^\d+$/.test(id);
} Try / catch
try {
const res = await resolveUrl(new URL(`artifact://${id}`));
} catch (err) {
if (err instanceof Error && err.message.startsWith("artifact:// ID must be numeric")) {
// route named IDs to agent:// instead
const res2 = await resolveUrl(new URL(`agent://${id}`));
} else throw err;
} Prevention
- Use artifact:// only for numeric counter IDs; named outputs go through agent://.
- Regex-check the ID against /^\d+$/ before building the URL.
- Strip extensions, whitespace, and sign characters from IDs taken from file names or user input.
- Use URL completion (ArtifactProtocolHandler.complete) to source valid IDs.
When it happens
Trigger: Calling artifact://reviewer_0, artifact://abc, artifact://3a, or artifact://-1 — any non-numeric host passed to resolveArtifactFile via ArtifactProtocolHandler.resolve.
Common situations: Confusing schemes: using artifact:// with an agent output ID like reviewer_0 (should be agent://reviewer_0); URL-encoded or percent-containing hosts; an ID copied with a suffix (e.g. '3.txt'); negative or whitespace-padded numbers.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- artifact:// URL requires a numeric ID: artifact://0
- No session - artifacts unavailable
- No artifacts directory found
- Invalid xd:// URL: ${url.href}. Use xd://<tool>.
- resultBaseUrl is not a valid URL
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e4745bf722f8c3ba.
Report an issue: GitHub.