paperclipai/paperclip · error · Error

${decision.message}

Error message

${decision.message}

What it means

Thrown by requirePaperclipIngestionPolicy() when evaluatePaperclipProfilePolicy() returns allowed=false. The message is the decision's own message, which can be one of: archived_space (space.status !== "active"), restricted_space (space.accessScope !== "shared"), profile_disabled (non-default space, requireEnabledProfile set, profile not enabled), or profile_empty (profile enabled but sourceScopes empty). The purpose (e.g. ingest, profile_update) is interpolated into each.

Source

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

async function requirePaperclipIngestionPolicy(
  ctx: PluginContext,
  input: { companyId: string; wikiId: string; spaceSlug?: string | null },
  purpose: PaperclipIngestionPolicyPurpose,
  options: { requireEnabledProfile?: boolean } = {},
): Promise<WikiSpace> {
  const space = await resolveSpace(ctx, {
    companyId: input.companyId,
    wikiId: input.wikiId,
    spaceSlug: input.spaceSlug,
  });
  const profile = await profileForSpace(ctx, input.companyId, space);
  const decision = evaluatePaperclipProfilePolicy({
    space,
    profile,
    purpose,
    requireEnabledProfile: options.requireEnabledProfile,
  });
  if (!decision.allowed) throw new Error(decision.message);
  return decision.space;
}

function assertPaperclipSourceScopePayload(input: { projectId?: string | null; rootIssueId?: string | null }) {
  if (input.projectId && input.rootIssueId) {
    throw new Error("Paperclip source scope must specify either projectId or rootIssueId, not both.");
  }
}

function assertRequestedCharacterLimit(name: string, value: unknown, max: number) {
  if (value == null) return;
  if (typeof value !== "number" || !Number.isFinite(value) || value < 1) {
    throw new Error(`${name} must be a positive number.`);
  }
  if (Math.floor(value) > max) {
    throw new Error(`${name} exceeds the hard Paperclip ingestion cap of ${max} characters.`);
  }
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Read the decision.message — it names the specific reason; address that reason (un-archive the space, switch accessScope to shared, enable the profile, or add a source scope).
  2. If you do not need a custom space, ingest against the default space (slug "default") where the profile gate does not apply.
  3. Call getPaperclipIngestionProfile() first to inspect policyBlocks and effectiveState before attempting the operation.

Example fix

// before
await requirePaperclipIngestionPolicy(ctx, { companyId, wikiId, spaceSlug: "my-team" }, "ingest", { requireEnabledProfile: true });
// after
// ensure profile is enabled with >=1 source scope, then:
await requirePaperclipIngestionPolicy(ctx, { companyId, wikiId, spaceSlug: "my-team" }, "ingest", { requireEnabledProfile: true });
Defensive patterns

Strategy: validation

Validate before calling

const profile = await getPaperclipIngestionProfile(ctx, { companyId, wikiId, spaceSlug });
if (profile.effectiveState === "policy_blocked") {
  throw new Error(`Cannot ingest: ${profile.policyBlocks.join("; ")}`);
}

Type guard

function isPolicyAllowed(d: { allowed: boolean }): d is { allowed: true } {
  return d.allowed === true;
}

Try / catch

try {
  await requirePaperclipIngestionPolicy(ctx, input, purpose, opts);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Paperclip ingestion policy denied")) {
    // read reason from message, fix space/profile, then retry or surface
  } else throw err;
}

Prevention

When it happens

Trigger: Attempting ingestion against an archived space. Against a non-shared (private) space. Against a non-default space whose profile is disabled or has no source scopes, when requireEnabledProfile is set.

Common situations: Trying to ingest Paperclip sources into a custom (non-default) wiki space before configuring an enabled profile with at least one source scope. Ingestion attempted after a space was archived. Access scope restricted to private before host permissions were wired.

Related errors


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