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
- 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).
- If you do not need a custom space, ingest against the default space (slug "default") where the profile gate does not apply.
- 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
- Inspect getPaperclipIngestionProfile().policyBlocks before ingesting.
- Configure an enabled profile with >=1 scope on custom spaces.
- Ingest against the default space to bypass the profile gate.
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
- Source content is ${sourceBytes} bytes, which exceeds the co
- ${policy.message}
- Ingest operation did not return an issue id; the dropped fil
- Paperclip source scope must specify either projectId or root
- ${name} must be a positive number.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/cedcf9b03c4b2fdf.
Report an issue: GitHub.