paperclipai/paperclip · error · Error
Unsafe SQL ${label}: ${value}
Error message
Unsafe SQL ${label}: ${value} What it means
Generic identifier guard (assertIdentifier): the supplied string (table/column/schema identifier passed by a plugin) fails IDENTIFIER_RE, so it could be unsafe to interpolate into SQL or DDL. The offending value's role is named by label; the plugin-supplied identifier is at fault.
Source
Thrown at server/src/services/plugin-database.ts:48
export function derivePluginDatabaseNamespace(
pluginKey: string,
namespaceSlug?: string,
): string {
const hash = createHash("sha256").update(pluginKey).digest("hex").slice(0, 10);
const slug = (namespaceSlug ?? pluginKey)
.toLowerCase()
.replace(/[^a-z0-9_]+/g, "_")
.replace(/^_+|_+$/g, "")
.replace(/_+/g, "_")
.slice(0, 36) || "plugin";
const namespace = `plugin_${slug}_${hash}`;
return namespace.slice(0, MAX_POSTGRES_IDENTIFIER_LENGTH);
}
function assertIdentifier(value: string, label = "identifier"): string {
if (!IDENTIFIER_RE.test(value)) {
throw new Error(`Unsafe SQL ${label}: ${value}`);
}
return value;
}
function quoteIdentifier(value: string): string {
return `"${assertIdentifier(value).replaceAll("\"", "\"\"")}"`;
}
function splitSqlStatements(input: string): string[] {
const statements: string[] = [];
let start = 0;
let quote: "'" | "\"" | null = null;
let lineComment = false;
let blockComment = false;
for (let i = 0; i < input.length; i += 1) {
const char = input[i]!;
const next = input[i + 1];View on GitHub (pinned to 120ae5428f)
Solutions
- Rewrite the plugin SQL to avoid the unsafe construct named in the message.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at server/src/services/plugin-database.ts:48 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/a9291a8349d0901a.
Report an issue: GitHub.