can1357/oh-my-pi · error · Error
(dynamic write-policy refusal message: throw new Error(refus
Error message
(dynamic write-policy refusal message: throw new Error(refusal))
What it means
When direct file mutation is allowed, the download path is still checked against the session's write policy (permissions/allowlist rules) via refuseByWritePolicy. If the policy disallows writing to that specific path, its human-readable refusal message is thrown verbatim. The message is dynamic — it names the path and the violated rule.
Source
Thrown at packages/coding-agent/src/cursor.ts:796
* native `delete` frame — on the session actually granting a file-writing
* tool, and on the user's `write`-tier policy. The gate runs before the read
* so a refused download never fetches the resource either.
*/
async readMcpResource({
server,
uri,
downloadPath,
}: {
server: string;
uri: string;
downloadPath?: string;
}): Promise<CursorMcpResourceContent | null> {
if (downloadPath) {
if (!allowsDirectFileMutation(this.options)) {
throw new Error('Tool "write" not available: this session cannot download resources to disk.');
}
const refusal = refuseByWritePolicy(this.options, "write", downloadPath);
if (refusal) throw new Error(refusal);
}
const mcp = this.options.mcpResources;
if (!mcp) return null;
const read = await mcp.readServerResource(server, uri);
if (!read) return null;
// The mime type must describe the bytes actually sent, not whatever item
// happened to be first: an image blob followed by a text note would
// otherwise label the text `image/png` and mislead the model about what
// it is holding. Each branch below takes the type from its own producer.
const textItems = read.contents.filter(item => item.text !== undefined);
const texts = textItems.map(item => item.text as string);
const blobItem = read.contents.find(item => item.blob !== undefined);
const blob = blobItem?.blob;
const textMimeType = textItems[0]?.mimeType;
const blobMimeType = blobItem?.mimeType;
if (downloadPath) {
// Text resources download as their own bytes; a blob decodes first.View on GitHub (pinned to 9690622007)
Solutions
- Read the refusal message — it names the path and rule; move the downloadPath inside the permitted area (typically the workspace).
- Update the write policy / permission rules (allow the directory or file glob) if the download is intentional.
- Approve the write when prompted by the permission system, or pre-authorize the path in settings.
- Download to the project directory instead of an absolute outside path.
Example fix
// before: outside allowed write roots
{ downloadPath: "/etc/app/config.yaml" }
// after: inside the workspace
{ downloadPath: "downloads/config.yaml" } Defensive patterns
Strategy: validation
Validate before calling
const refusal = refuseByWritePolicy(options, "write", downloadPath);
if (refusal) {
// don't attempt the download; show the refusal to the user
console.warn(refusal);
} else {
await readMcpResource({ server, uri, downloadPath });
} Try / catch
try {
return await readMcpResource({ server, uri, downloadPath });
} catch (e) {
if (/not (allowed|permitted)|write policy|outside/i.test(String(e.message))) {
// retry with a path inside the permitted write roots
return readMcpResource({ server, uri, downloadPath: withinWorkspace(downloadPath) });
} else throw e;
} Prevention
- Pre-authorize download directories in the write policy before requesting downloads.
- Keep downloadPath inside directories the policy allows (usually the workspace).
- Read and honor the dynamic refusal message — it names the offending path/rule.
When it happens
Trigger: readMcpResource with a downloadPath that the write policy rejects: outside approved directories, matching a deny glob, or blocked by user-configured permission rules when the write tool itself is enabled.
Common situations: Downloading to a path outside the workspace allowlist; a deny rule for config or credential files; organization policy restricting writes to certain directories.
Related errors
- Tool "write" not available: this session cannot download res
- ENXIO
- Refusing to download onto a non-regular file: ${absolutePath
- Refusing to download onto a file with ${stat.nlink} hard lin
- Refusing to download outside the workspace: ${downloadPath}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c60580649c55b5d2.
Report an issue: GitHub.