paperclipai/paperclip · error · PhotonError

network

network

Error message

Photon Cloud could not be reached; retry the connection

What it means

Thrown by PhotonCloudClient.request when the fetch to https://spectrum.photon.codes throws (network failure, DNS failure, TLS error, or the 15-second AbortSignal timeout). The client converts any transport-level exception into a PhotonError with code 'network' telling the caller the Photon Cloud could not be reached and to retry.

Solutions

  1. Verify basic connectivity: curl https://spectrum.photon.codes from the same host
  2. Retry with backoff; the message explicitly frames this as transient
  3. Check DNS/proxy settings (HTTPS_PROXY, corporate firewalls) that could block spectrum.photon.codes
  4. Investigate whether requests consistently take >15s; if so the 15s AbortSignal.timeout is too tight for your environment
  5. Check Photon status/announcements for an ongoing outage

Example fix

// before
const client = new PhotonCloudClient();
// after: inject a custom fetch with proxy support or longer timeout
const client = new PhotonCloudClient((input, init) =>
  fetch(input, { ...init, signal: AbortSignal.timeout(30_000) }));
Defensive patterns

Strategy: retry

Validate before calling

// cheap preflight before Photon calls
const reachable = await fetch("https://spectrum.photon.codes", { method: "HEAD", signal: AbortSignal.timeout(5000) }).then(r => r.ok).catch(() => false);
if (!reachable) throw new Error("Photon Cloud unreachable from this host");

Type guard

null

Try / catch

try {
  return await cloud.inspect(projectId, secret);
} catch (e) {
  if (e instanceof PhotonError && e.code === "network")
    return retryWithBackoff(() => cloud.inspect(projectId, secret), { attempts: 3, baseMs: 1000 });
  throw e;
}

Prevention

When it happens

Trigger: fetchImpl rejects: no internet/DNS resolution failure, spectrum.photon.codes unreachable, TLS handshake failure, or AbortSignal.timeout(15_000) fires before the response headers arrive; also redirect: 'error' turns an HTTP redirect into a fetch rejection.

Common situations: Corporate proxy or firewall blocks the Photon Cloud host; offline dev machine or container; Photon Cloud outage; slow response exceeding the 15s timeout; the Cloud endpoint starts redirecting (e.g. to a login page) after a service change.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/9e29c2a858ab2875. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/photon/cloud.ts:136

    photonProjectIdSchema.parse(projectId);
    if (!projectSecret || projectSecret.length > 4096)
      throw new PhotonError("credentials", "Enter a Photon project secret");
    let response: Response;
    try {
      response = await this.fetchImpl(
        `${CLOUD_ORIGIN}/projects/${encodeURIComponent(projectId)}/${suffix}`,
        {
          method,
          redirect: "error",
          signal: AbortSignal.timeout(15_000),
          headers: {
            authorization: `Basic ${Buffer.from(`${projectId}:${projectSecret}`).toString("base64")}`,
            accept: "application/json",
          },
        },
      );
    } catch {
      throw new PhotonError(
        "network",
        "Photon Cloud could not be reached; retry the connection",
      );
    }
    if (response.status === 401 || response.status === 403)
      throw new PhotonError(
        "credentials",
        "Photon rejected this project ID or secret",
      );
    if (response.status === 429)
      throw new PhotonError(
        "quota",
        "Photon Cloud request limit reached; retry later",
      );
    if (!response.ok)
      throw new PhotonError(
        "network",
        `Photon Cloud returned HTTP ${response.status}`,

View on GitHub (pinned to 3f1d897a7c)