can1357/oh-my-pi · error

Host URI write failed for ${url.href}

Error message

Host URI write failed for ${url.href}

What it means

Thrown by RpcHostConnection.requestWrite (packages/coding-agent/src/modes/rpc/host-uris.ts:175) when the host-side 'write' dispatch for a host URI returns an error result. The thrown message is the host's own error text if present, otherwise this generic fallback naming the URI. It signals the child/host refused or failed a host-mediated resource write.

Source

Thrown at packages/coding-agent/src/modes/rpc/host-uris.ts:175

			throw new Error(result.error || result.content || `Host URI read failed for ${url.href}`);
		}
		const content = result.content ?? "";
		const contentType = result.contentType ?? "text/plain";
		const definition = this.#definitions.get(scheme);
		return {
			url: url.href,
			content,
			contentType,
			size: Buffer.byteLength(content, "utf-8"),
			notes: result.notes && result.notes.length > 0 ? [...result.notes] : undefined,
			immutable: result.immutable ?? definition?.immutable === true,
		};
	}

	async requestWrite(_scheme: string, url: InternalUrl, content: string, context?: WriteContext): Promise<void> {
		const result = await this.#dispatch("write", url.href, content, context?.signal);
		if (result.isError) {
			throw new Error(result.error || result.content || `Host URI write failed for ${url.href}`);
		}
	}

	#dispatch(
		operation: "read" | "write",
		url: string,
		content: string | undefined,
		signal: AbortSignal | undefined,
	): Promise<RpcHostUriResult> {
		if (signal?.aborted) {
			return Promise.reject(new Error(`Host URI ${operation} for ${url} was aborted`));
		}

		const id = Snowflake.next() as string;
		const { promise, resolve, reject } = Promise.withResolvers<RpcHostUriResult>();
		let settled = false;

		const cleanup = () => {

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the thrown message (or result.error) for the host's underlying reason and fix that condition (permissions, resource state).
  2. Verify the scheme is registered as writable on the host before calling requestWrite.
  3. Pass a fresh AbortSignal only if cancellation is intended; a pre-aborted signal yields an immediate error.
  4. If the resource is read-only, use requestRead instead of requestWrite.

Example fix

// before
await connection.requestWrite("file", url, content, { signal: staleSignal });
// after
if (!staleSignal.aborted) {
  await connection.requestWrite("file", url, content);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (signal?.aborted) throw new Error("write aborted before dispatch");
if (typeof content !== "string") throw new Error("write content must be a string");

Type guard

function isHostUrl(u: unknown): u is URL {
  return u instanceof URL && u.protocol !== "http:" && u.protocol !== "https:";
}

Try / catch

try {
  await connection.requestWrite(scheme, url, content, { signal });
} catch (err) {
  logger.warn("host URI write failed", { href: url.href, cause: String(err) });
  // surface to user or fall back to read-only handling
}

Prevention

When it happens

Trigger: Calling requestWrite where this.#dispatch("write", url.href, content, signal) resolves with isError=true — the host rejected the write (permission denied, read-only resource) or returned an empty/error payload (result.error and result.content both empty yields the generic message).

Common situations: An agent session writes a resource the host has not granted write access to; the host tool handler throws internally; the user denies a permission prompt; the write is aborted via the supplied AbortSignal and the host reports it as an error.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d8c1a6db4df2a417. Report an issue: GitHub.