paperclipai/paperclip · error · Error

Refusing to overwrite protected wiki control file ${path}; b

Error message

Refusing to overwrite protected wiki control file ${path}; board-managed edits must use the wiki UI.

What it means

Thrown by assertPageWriteAllowed when writer is not 'board_ui' and the target path is in PROTECTED_WIKI_CONTROL_FILES (AGENTS.md or IDEA.md). These control files are board-managed; agents and other writers cannot overwrite them directly and must go through the wiki UI flow.

Source

Thrown at packages/plugins/plugin-llm-wiki/src/wiki/core.ts:1195

    throw new Error(`Wiki path must stay inside AGENTS.md, IDEA.md, raw/, or wiki/: ${path}`);
  }
  return trimmed;
}

function assertPagePath(path: string): string {
  const normalized = assertWikiPath(path);
  if (normalized !== "index.md" && normalized !== "log.md" && normalized !== "WIKI.md" && normalized !== "AGENTS.md" && normalized !== "IDEA.md" && !normalized.startsWith("wiki/")) {
    throw new Error(`Wiki page writes must target AGENTS.md, IDEA.md, or wiki/: ${path}`);
  }
  if (!normalized.endsWith(".md")) {
    throw new Error(`Wiki page path must be a markdown file: ${path}`);
  }
  return normalized;
}

function assertPageWriteAllowed(path: string, writer: WritePageInput["writer"] = "agent_tool"): void {
  if (writer !== "board_ui" && PROTECTED_WIKI_CONTROL_FILES.has(path)) {
    throw new Error(`Refusing to overwrite protected wiki control file ${path}; board-managed edits must use the wiki UI.`);
  }
}

function assertRawPath(path: string): string {
  const normalized = assertWikiPath(path);
  if (!normalized.startsWith("raw/")) {
    throw new Error(`Source path must stay inside raw/: ${path}`);
  }
  return normalized;
}

function tableName(namespace: string, table: string): string {
  return `${namespace}.${table}`;
}

function spaceTable(ctx: PluginContext): string {
  return tableName(ctx.db.namespace, "wiki_spaces");
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Route edits to AGENTS.md / IDEA.md through the board UI (writer: 'board_ui').
  2. For agent-authored content, write under wiki/ instead of overwriting the control file.
  3. If an automated board flow is intended, explicitly set writer: 'board_ui' on the call.

Example fix

// before
await writePage(ctx, { companyId, path: "AGENTS.md", content, writer: "agent_tool" });

// after
// Option A: route through the board UI flow
await writePage(ctx, { companyId, path: "AGENTS.md", content, writer: "board_ui" });
// Option B: write agent content elsewhere
await writePage(ctx, { companyId, path: "wiki/agent-notes.md", content, writer: "agent_tool" });
Defensive patterns

Strategy: type-guard

Validate before calling

const PROTECTED = new Set(["AGENTS.md", "IDEA.md"]);
function assertPageWriteAllowed(path, writer = "agent_tool") {
  if (writer !== "board_ui" && PROTECTED.has(path)) {
    throw new Error(`Refusing to overwrite protected wiki control file ${path}`);
  }
}

Type guard

function isProtectedControlFile(path) {
  return PROTECTED.has(String(path).trim().replace(/^\/+/, ""));
}

Try / catch

try {
  await writePage(ctx, { companyId, path, content, writer });
} catch (err) {
  if (/protected wiki control file/.test(err.message)) {
    if (canUseBoardUi) return writePage(ctx, { companyId, path, content, writer: "board_ui" });
    return writePage(ctx, { companyId, path: "wiki/agent-notes.md", content, writer: "agent_tool" });
  }
  throw err;
}

Prevention

When it happens

Trigger: An agent_tool (or any non-board_ui writer) calling writePage against 'AGENTS.md' or 'IDEA.md'.

Common situations: Agent trying to self-edit its instructions file; script bulk-updating control files; using the default writer ('agent_tool') for a board-owned file.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/9d49143cb2a2e693. Report an issue: GitHub.