can1357/oh-my-pi · error
agent:// URL cannot combine path extraction with ?q=
Error message
agent:// URL cannot combine path extraction with ?q=
What it means
agent:// URLs support two mutually exclusive extraction mechanisms: a slash path (agent://<id>/<path>) and a query string (agent://<id>?q=<query>). If a URL supplies both a non-trivial pathname and a non-empty ?q= parameter, the handler cannot decide which extraction to apply and throws. This is a strict ambiguity check on URL shape.
Source
Thrown at packages/coding-agent/src/internal-urls/agent-protocol.ts:49
* with optional JSON extraction.
*/
export class AgentProtocolHandler implements ProtocolHandler {
readonly scheme = "agent";
readonly immutable = true;
async resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource> {
const outputId = url.rawHost || url.hostname;
if (!outputId) {
throw new Error("agent:// URL requires an output ID: agent://<id>");
}
const urlPath = url.pathname;
const queryParam = url.searchParams.get("q");
const hasPathExtraction = urlPath && urlPath !== "/" && urlPath !== "";
const hasQueryExtraction = queryParam !== null && queryParam !== "";
if (hasPathExtraction && hasQueryExtraction) {
throw new Error("agent:// URL cannot combine path extraction with ?q=");
}
const registry = AgentRegistry.global();
const rootSessionFile = context?.sessionFile
? await ensurePersistedRoster(registry, context.sessionFile)
: undefined;
// The caller root's canonical artifact directory (its session file minus
// the `.jsonl` suffix) is scanned FIRST, ahead of every process-global
// registry dir. The roster ref this refresh installs for the caller's
// parked id contributes only its nested child dir, not the root dir that
// actually holds `<id>.md` — and with two coexisting roots the global
// `Main` ref can belong to the other root, whose dir would otherwise win
// the first-hit id map for a shared id. No caller session file: keep the
// pre-existing global scan untouched.
const dirs = artifactsDirsFromRegistry(
rootSessionFile ? { preferredDir: rootSessionFile.slice(0, -6) } : undefined,
);
if (dirs.length === 0) {View on GitHub (pinned to 9690622007)
Solutions
- Remove the ?q= parameter and express the extraction as a path, keeping one mechanism
- Or remove the path portion so only ?q= remains: agent://<id>?q=<query>
- If building URLs dynamically, strip the pathname when a q param is present (or vice versa)
Example fix
// before
await handler.resolve(parseUrl("agent://out1/foo/bar?q=.items[0]"), ctx);
// after
await handler.resolve(parseUrl("agent://out1?q=.foo.bar.items[0]"), ctx); Defensive patterns
Strategy: validation
Validate before calling
const hasPath = url.pathname && url.pathname !== "/";
const hasQuery = url.searchParams.get("q") !== null && url.searchParams.get("q") !== "";
if (hasPath && hasQuery) throw new Error("agent:// URL cannot combine path extraction with ?q="); Type guard
function usesSingleExtraction(url: InternalUrl): boolean {
const hasPath = Boolean(url.pathname && url.pathname !== "/");
const q = url.searchParams.get("q");
const hasQuery = q !== null && q !== "";
return !(hasPath && hasQuery);
} Prevention
- Pick one extraction form per URL: path OR ?q=, never both
- When appending ?q= programmatically, clear the pathname first
- Document the two URL forms (path extraction vs query extraction) for URL builders
When it happens
Trigger: Calling resolve() with a URL that has both a pathname other than '' and '/', and a non-empty 'q' search param — e.g. 'agent://out1/foo/bar?q=.items[0]' or 'agent://out1/data.json?q=results'.
Common situations: Appending ?q= to a URL that already contains a path-based extraction (copy-pasted from an example that used the other form); code that programmatically appends query params to a base URL that already has path segments; migrating between the two extraction forms and leaving both in place.
Related errors
- agent:// URL requires an output ID: agent://<id>
- Provider delete URL must not embed an account credential
- ${destination} returned an invalid upload URL
- Destination option endpoint must be an absolute URL
- Destination option endpoint must use HTTP or HTTPS
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/456238312a63bb04.
Report an issue: GitHub.