can1357/oh-my-pi · error
imageUrls exposure "bore" requires options.server
Error message
imageUrls exposure "bore" requires options.server
What it means
The bore exposure adapter requires a `server` option naming the bore relay host (defaulting to "bore.pub"). This guard throws when the resolved server option is present-but-empty (optionString returned an empty string), since a bore client cannot connect to a blank relay address. It is a configuration validation error before any process is spawned.
Source
Thrown at packages/coding-agent/src/blob-broker/exposure.ts:453
const binary = requireBinary("devtunnel");
const { proc, baseUrl } = await spawnUrlTunnel(
[binary, "host", "-p", String(port), "--allow-anonymous", "--protocol", "http"],
parseDevtunnelUrl,
);
return processExposure("devtunnel", baseUrl, proc);
}
case "zrok": {
const binary = requireBinary("zrok");
const { proc, baseUrl } = await spawnUrlTunnel(
[binary, "share", "public", `http://127.0.0.1:${port}`, "--headless", "--backend-mode", "proxy"],
parseZrokUrl,
);
return processExposure("zrok", baseUrl, proc);
}
case "bore": {
const binary = requireBinary("bore");
const server = optionString(config, "server", "bore.pub");
if (!server) throw new Error('imageUrls exposure "bore" requires options.server');
const secret = credentialString(config, "secret");
const argv = [binary, "local", String(port), "--to", server];
if (secret) argv.push("--secret", secret);
const { proc, baseUrl } = await spawnUrlTunnel(argv, line => parseBoreUrl(line, server));
return processExposure("bore", baseUrl, proc);
}
case "named-cloudflared": {
if (!config.publicBaseUrl) {
throw new Error('imageUrls exposure "named-cloudflared" requires imageUrls.publicBaseUrl');
}
const binary = requireBinary("cloudflared");
const token = credentialString(config, "tunnelToken");
let argv: string[];
if (token) {
argv = [binary, "tunnel", "--no-autoupdate", "run", "--token", token];
} else {
const configFile = optionString(config, "configFile");
const tunnelName = optionString(config, "tunnelName");View on GitHub (pinned to 9690622007)
Solutions
- Set options.server to a valid bore relay host, or remove the key entirely to use the "bore.pub" default.
- Validate the config before saving: reject empty strings for server.
- Run your own bore server and point server at it if bore.pub is unreliable.
Example fix
// before
"bore": { "options": { "server": "" } }
// after
"bore": { "options": { "server": "bore.pub" } } Defensive patterns
Strategy: validation
Validate before calling
if (config.kind === "bore") {
const server = config.options.server ?? "bore.pub";
if (typeof server !== "string" || server.trim() === "") {
throw new Error("bore exposure: options.server must be a non-empty host");
}
} Type guard
function hasBoreServer(o: unknown): o is { server: string } {
return typeof o === "object" && o !== null && "server" in o &&
typeof (o as { server: unknown }).server === "string" &&
(o as { server: string }).server.trim().length > 0;
} Prevention
- Omit the server key instead of setting it to an empty string
- Validate config at load time: no empty-string options
- Use the built-in "bore.pub" default unless running your own relay
When it happens
Trigger: Configuring imageUrls exposure kind "bore" with `options.server` set to an empty string; optionString's default only applies when the key is missing, not when it is explicitly empty.
Common situations: A config file has `server = ""` or an env var interpolation that resolves to empty; a settings UI saved an empty field instead of clearing the key.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains an empty provider
- OMP_AUTH_BROKER_ACCOUNT_POOL_FILE contains a provider id wit
- ${name} path does not exist: ${trimmed}
- Anthropic thinking budget requires max_tokens greater than $
- cachedContent must not be blank
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c4518612b1bdfb1e.
Report an issue: GitHub.