langfuse/langfuse · warning · Error

Failed to upload attachments to Pylon.

Error message

Failed to upload attachments to Pylon.

What it means

The support-chat form uploads attachments to a Pylon endpoint; if the response is not ok and the response body contains no error field, this generic message is thrown. It means the upload HTTP request failed for some reason (auth, size limit, server error) without a structured error body.

Source

Thrown at web/src/features/support-chat/SupportFormSection.tsx:286

        const base64 = btoa(
          new Uint8Array(arrayBuffer).reduce(
            (data, byte) => data + String.fromCharCode(byte),
            "",
          ),
        );
        return { fileName: file.name, fileBase64: base64 };
      }),
    );

    const res = await fetch("/api/support/upload-attachments", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ files: filePayloads }),
    });

    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      throw new Error(
        (body as { error?: string }).error ??
          "Failed to upload attachments to Pylon.",
      );
    }

    const body = (await res.json()) as { attachment_urls: string[] };
    return body.attachment_urls;
  }

  const onSubmit = async (values: SupportFormInput) => {
    const parsed: SupportFormValues = SupportFormSchema.parse(values);
    const msgLen = (parsed.message ?? "").trim().length;

    if (msgLen < 50 && !warnedShortOnce) {
      setWarnedShortOnce(true);
      return;
    }

View on GitHub (pinned to 59d92c7cf3)

Solutions

  1. Inspect the network tab for the actual status code and response body of the failed upload
  2. Reduce attachment size/count and retry; compress screenshots before upload
  3. Verify you are authenticated (session cookie present) when the support form loads
  4. If a gateway/proxy error page is returned, raise its request body limit (e.g. nginx client_max_body_size)

Example fix

// before
if (!res.ok) {
  const body = await res.json().catch(() => ({}));
  throw new Error((body as { error?: string }).error ?? "Failed to upload attachments to Pylon.");
}

// after
if (!res.ok) {
  const body = await res.json().catch(() => ({}));
  throw new Error((body as { error?: string }).error ?? `Upload failed (HTTP ${res.status})`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const MAX_BYTES = 5 * 1024 * 1024;
if (files.some((f) => f.size > MAX_BYTES)) {
  setError("Each attachment must be under 5 MB.");
  return;
}

Type guard

const isPylonUploadError = (err: unknown): boolean =>
  err instanceof Error && /Pylon/i.test(err.message);

Try / catch

try {
  await uploadFilesToPylon(files);
} catch (err) {
  if (err instanceof Error && err.message.includes("Pylon")) {
    setError(`Attachment upload failed: ${err.message}. Try smaller files or submit without attachments.`);
    return; // allow form submit without attachments as fallback
  }
  throw err;
}

Prevention

When it happens

Trigger: POSTing { files: [...] } to the Pylon upload route and receiving a non-2xx status with an unparseable or error-less body — e.g. 413 payload too large, 401/403 auth failure, 500 from Pylon, or a proxy/gateway (nginx, Cloudflare) returning an HTML error page that fails JSON parsing.

Common situations: Attaching files above the proxy or Pylon size limit; expired/missing session for the support chat; Pylon API outage or rate limit; Cloudflare 413/52x pages replacing the JSON error.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of langfuse/langfuse@59d92c7cf3 (2026-08-27). Data as JSON: /api/errors/64f0eaca6e9ec03d. Report an issue: GitHub.