paperclipai/paperclip · error · RailwayError
railway_output_limit
railway_output_limit
Error message
Railway's response exceeded the limit. Request fewer results or a shorter log interval.
What it means
RailwayError (code railway_output_limit) thrown by boundedResponseText when the accumulated response body exceeds 1 MiB (1024 * 1024 bytes). The library caps Railway API responses (logs, list endpoints) to protect memory, and instructs callers to narrow the request rather than growing the cap.
Solutions
- Narrow the request: request fewer log results or a shorter time window / coarser interval, as the message advises
- Paginate: use the Railway API's cursor/pagination and fetch in chunks, processing each bounded page separately
- Filter server-side where possible (specific deployment id, severity level) instead of downloading everything
- If genuinely needed, raise the 1 MiB cap in a fork/patch knowingly — the limit is a deliberate memory guard
Example fix
// before
const text = await railway.logs({ deploymentId, limit: 10000 }); // > 1MiB
// after
const text = await railway.logs({ deploymentId, limit: 500, since: oneHourAgo }); // stay under the limit; page for more Defensive patterns
Strategy: try-catch
Validate before calling
// Cap the request server-side before reading
const params = new URLSearchParams({ limit: String(Math.min(requestedLimit, 500)) });
if (rangeMs > MAX_LOG_WINDOW_MS) throw new Error("Narrow the log window to stay under the 1MiB response limit"); Type guard
null
Try / catch
try {
const text = await boundedResponseText(res, signal);
} catch (e) {
if (e.code === "railway_output_limit") {
logger.warn("Railway response exceeded 1MiB; retrying with a smaller window");
return fetchRailwayLogs({ ...opts, limit: Math.floor(opts.limit / 4), since: narrowerWindow });
}
throw e;
} Prevention
- Request bounded result sets (small limits, short time windows) from Railway list/log endpoints
- Paginate and process chunks instead of one large pull
- Filter logs server-side (deployment id, severity) to shrink payloads
- Expect ~1MiB as the hard cap; never design flows that need full unbounded log downloads in one call
When it happens
Trigger: Streaming a Railway deployment log tail or large list response whose byte count passes 1048576 while reading chunks — e.g. requesting too many log entries, too wide a time window, or verbose services emitting megabytes of output.
Common situations: Fetching full historical deployment logs for a chatty service; listing hundreds of environments/plugins in one call; log interval set too fine (per-line streaming over hours); a service stuck in a crash-loop generating enormous logs.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- railway_invalid_response
- Announcement request failed
- Anthropic Managed Agents request failed with HTTP
- Artifact download failed: HTTP
- `}
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/75dbc3a02ef54024.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/railway.ts:157
rollback: `mutation PaperclipRailwayRollback($deploymentId:String!) { deploymentRollback(id:$deploymentId) }`,
};
function record(value: unknown): Record<string, any> {
return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, any> : {};
}
async function boundedResponseText(response: Response, signal: AbortSignal): Promise<string> {
const reader = response.body?.getReader();
if (!reader) throw new RailwayError("railway_invalid_response", "Railway returned an empty response.");
const chunks: Uint8Array[] = [];
let size = 0;
try {
for (;;) {
signal.throwIfAborted();
const { done, value } = await reader.read();
if (done) break;
size += value.byteLength;
if (size > 1024 * 1024) throw new RailwayError("railway_output_limit", "Railway's response exceeded the limit. Request fewer results or a shorter log interval.");
chunks.push(value);
}
} finally { await reader.cancel().catch(() => {}); }
return Buffer.concat(chunks).toString("utf8");
}
/** Discover a consented workspace without requesting account-wide API access. */
export async function discoverRailwayWorkspace(options: RailwayClientOptions): Promise<string> {
const send = (init: RequestInit) => options.request(RAILWAY_MCP_URL, { ...init, redirect: "error", signal: options.signal });
const headers = { Authorization: options.authorization };
const list = (requestHeaders: Record<string, string>) => send({
method: "POST", headers: mcpHttpRequestHeaders(requestHeaders),
body: JSON.stringify({ jsonrpc: "2.0", id: "paperclip-railway-workspace-probe", method: "tools/call", params: { name: "list-workspaces", arguments: {} } }),
});
let response = await list(headers);
if (response.status === 400) {
await response.body?.cancel();
response = await list(await initializeMcpHttpSession({ send, headers, requestId: "paperclip-railway-workspace-probe" }));View on GitHub (pinned to 3f1d897a7c)