paperclipai/paperclip · error · RequestFailure
invalid_response
invalid_response
Error message
invalid_response
What it means
request() in the Discord command-registration reconciler validates requestTimeoutMs before making the Discord API call; if it is not an integer between 1 and 25000 inclusive it throws a RequestFailure with code 'invalid_response'. The message is terse because the guard runs before any network I/O — it is a pre-flight configuration validation, not Discord's reply.
Source
Thrown at server/src/services/chat-discord-command-registration.ts:322
function abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {
return new Promise<T>((resolve, reject) => {
const abort = () => reject(new RequestFailure("request_failed"));
signal.addEventListener("abort", abort, { once: true });
if (signal.aborted) abort();
promise
.then(resolve, reject)
.finally(() => signal.removeEventListener("abort", abort));
});
}
async function request(
input: ReconcileDiscordCommandRegistrationOptions,
method: "GET" | "POST" | "PATCH",
commandId?: string,
): Promise<unknown> {
const timeoutMs = input.requestTimeoutMs ?? 25_000;
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 25_000)
throw new RequestFailure("invalid_response");
const signal = AbortSignal.timeout(timeoutMs);
let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
try {
const response = await abortable(
input.fetch(
`https://discord.com/api/v10/applications/${input.scope.applicationId}/commands${commandId ? `/${commandId}` : ""}`,
{
method,
signal,
redirect: "error",
headers: {
authorization: `Bot ${input.botToken}`,
...(method === "GET" ? {} : { "content-type": "application/json" }),
},
...(method === "GET"
? {}
: {
body: JSON.stringify(View on GitHub (pinned to 01ad858492)
Solutions
- Set input.requestTimeoutMs to an integer between 1 and 25000 (e.g. 25000 for the maximum).
- Omit requestTimeoutMs entirely to use the default of 25000.
- Check the units — pass milliseconds, not seconds, and parse env values with Number() guarding against NaN.
- Clamp the value on the caller side: Math.min(25000, Math.max(1, Math.floor(ms))).
Example fix
// before
reconcile({ ..., requestTimeoutMs: Number(process.env.TIMEOUT_S) }) // '30' -> 30000 -> RequestFailure invalid_response
// after
const ms = Math.min(25000, Math.max(1, Math.floor(Number(process.env.TIMEOUT_S) * 1000 || 25000)));
reconcile({ ..., requestTimeoutMs: ms }); Defensive patterns
Strategy: validation
Validate before calling
if (!Number.isInteger(requestTimeoutMs) || requestTimeoutMs < 1 || requestTimeoutMs > 25000) throw new Error('requestTimeoutMs must be an integer in [1, 25000] ms'); Type guard
const isValidTimeoutMs = (v) => Number.isInteger(v) && v >= 1 && v <= 25000;
Try / catch
try {
return await reconcileDiscordCommands(input);
} catch (e) {
if (e?.code === 'invalid_response') {
return reconcileDiscordCommands({ ...input, requestTimeoutMs: 25000 }); // fall back to default
}
throw e;
} Prevention
- Pass milliseconds, not seconds, for requestTimeoutMs.
- Omit the field to use the default 25000 ms instead of computing a custom value.
- Clamp config-derived values to the [1, 25000] range before calling.
- Guard Number(env) results against NaN before use.
When it happens
Trigger: Calling the reconciler (reconcileDiscordCommandRegistration path) with input.requestTimeoutMs set to 0, a negative number, a non-integer (e.g. 1500.5), or greater than 25000 (e.g. 60000 for a slow network).
Common situations: Operator sets a timeout above the 25s ceiling in config; a duration in seconds (e.g. 30) passed where milliseconds are expected (0.03 would also fail the integer check... 30 fails as <1ms semantics confusion); NaN from an unparsed env var like Number('25s').
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- --agent-name cannot be empty.
- Invalid Discord command registration authority
- ${prefix}: "timeoutPolicy" must be one of ${ADAPTER_LOGIN_TI
- ${label} must be an integer between 1 and ${maximum}.
- PAPERCLIP_EVAL_MAX_CAMPAIGN_COST_USD must be a positive fini
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/b478e99161669f98.
Report an issue: GitHub.