paperclipai/paperclip · error
Capability live messages cannot be empty
Error message
Capability live messages cannot be empty
What it means
CapabilityLiveSession.sendMessage rejects empty messages. The incoming string is trimmed and if the result has length 0 the method throws before any transport work is done, because an empty user turn would create a meaningless Codex turn.
Source
Thrown at packages/paperclip-runner/src/live/live-session.ts:1461
) {
throw new Error("capability_live_attempt_active_turn");
}
attempt.status = status;
attempt.finishedAt = this.#now().toISOString();
attempt.failureCode = status === "failed"
? requireNonEmpty(failureCode ?? "attempt_failed", "attempt_failure_code")
: null;
await this.#persist();
return this.snapshot();
}
async sendMessage(
message: string,
/** Launch-only diagnostics may opt out; qualification campaigns must not. */
options: { allowMissingUsage?: boolean } = {},
): Promise<CapabilityLiveTurnResult> {
const value = message.trim();
if (value.length === 0) throw new Error("Capability live messages cannot be empty");
if (this.#status === "suspended" || this.#transport === null) {
await this.#connect(true);
}
if (this.#transport === null || this.#status === "closed" || this.#status === "failed") {
throw new Error("Capability live session is not connected");
}
if (
this.#activeTurnId !== null ||
this.#turnWaiter !== null ||
this.#pendingTurnAdmission !== null
) {
throw new Error("Capability live session already has an active turn");
}
let settleAdmission!: () => void;
const admission: PendingTurnAdmission = {
transport: this.#transport,
cancellation: null,
settled: new Promise<void>((resolveSettled) => {View on GitHub (pinned to 01ad858492)
Solutions
- Provide a non-empty message string
- Trim/validate user input before calling sendMessage and skip the call when empty
- Check whether an upstream field defaults to '' and supply a real prompt
Example fix
// before await session.sendMessage(userInput); // '' or whitespace throws // after const trimmed = (userInput ?? '').trim(); if (trimmed.length > 0) await session.sendMessage(trimmed);
Defensive patterns
Strategy: validation
Validate before calling
const trimmed = (message ?? '').trim();
if (trimmed.length === 0) throw new Error('refusing to send empty live message'); Type guard
function isSendableMessage(m: unknown): m is string {
return typeof m === 'string' && m.trim().length > 0;
} Try / catch
try {
await session.sendMessage(message);
} catch (e) {
if ((e as Error).message === 'Capability live messages cannot be empty') {
// skip turn; fix input source
} else throw e;
} Prevention
- Validate/trim chat input in the UI before dispatching
- Never pass optional message fields straight through; default and check them
- Add a unit assertion that prompt templates render to non-empty text
When it happens
Trigger: Calling sendMessage('') or sendMessage(' \n') — any string that is empty after trimming.
Common situations: UI sending an empty input box value; a pipeline forwarding an optional message field that is undefined coerced to empty string; templated prompts that resolve to whitespace only.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Invalid status '${String(rawStatus)}'. Must be one of: ${PLU
- "tool" is required and must be a string
- "runContext" is required and must be an object
- "runContext" must include agentId, runId, companyId, and pro
- ${prefix}: the capability must be an object.
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/5b1ac4ee56f1b000.
Report an issue: GitHub.