nexu-io/open-design · warning · Error

petshare list page ${page} failed: ${resp.status} ${resp.sta

Error message

petshare list page ${page} failed: ${resp.status} ${resp.statusText}

What it means

Thrown by listPetSharePets when the HTTP GET to the PetShare catalog API (PETSHARE_BASE/api/pets?page=N&pageSize=24) returns a non-2xx status. The error message includes the page number and the HTTP status+statusText for diagnostics. This is a transient external-dependency failure — the Supabase-hosted PetShare function is unreachable or returning an error.

Source

Thrown at apps/daemon/src/community-pets-sync.ts:117

async function pathExists(p: string): Promise<boolean> {
  try {
    await stat(p);
    return true;
  } catch {
    return false;
  }
}

async function listPetSharePets(limit: number | null): Promise<PetTask[]> {
  const tasks: PetTask[] = [];
  let page = 1;
  const pageSize = 24;
  for (;;) {
    const url = `${PETSHARE_BASE}/api/pets?page=${page}&pageSize=${pageSize}`;
    const resp = await fetch(url);
    if (!resp.ok) {
      throw new Error(`petshare list page ${page} failed: ${resp.status} ${resp.statusText}`);
    }
    const data = (await resp.json()) as PetShareListResponse;
    for (const pet of data.pets ?? []) {
      const folder = sanitizeFolder(pet.id);
      if (!folder) continue;
      const spritesheetUrl = pet.spritesheetUrl?.startsWith('http')
        ? pet.spritesheetUrl
        : `${PETSHARE_BASE}${pet.spritesheetUrl ?? ''}`;
      const ext = extOf(pet.spritesheetPath ?? spritesheetUrl);
      tasks.push({
        source: 'petshare',
        folder,
        manifest: {
          id: pet.id,
          displayName: pet.displayName,
          description: pet.description ?? '',
          spritesheetPath: `spritesheet.${ext}`,
          author: pet.ownerName,

View on GitHub (pinned to 5be4028344)

Solutions

  1. Retry the sync after a short delay — PetShare outages are typically transient.
  2. Check if the PETSHARE_BASE Supabase project is active and the edge function is deployed.
  3. If rate-limited, reduce sync frequency or add backoff.
  4. Use source: 'hatchery' as a fallback if only PetShare is down.

Example fix

// before — single fetch with no retry
const resp = await fetch(url);
if (!resp.ok) throw new Error(`petshare list page ${page} failed: ${resp.status}`);

// after — retry with backoff
for (let attempt = 0; attempt < 3; attempt++) {
  const resp = await fetch(url);
  if (resp.ok) break;
  if (attempt === 2 || resp.status < 500) {
    throw new Error(`petshare list page ${page} failed: ${resp.status} ${resp.statusText}`);
  }
  await new Promise(r => setTimeout(r, 1000 * (attempt + 1)));
}
Defensive patterns

Strategy: retry

Validate before calling

// Before syncing, probe PetShare availability with a lightweight HEAD request.
async function isPetShareReachable(): Promise<boolean> {
  try {
    const resp = await fetch(`${PETSHARE_BASE}/api/pets?page=1&pageSize=1`, {
      method: 'HEAD',
      signal: AbortSignal.timeout(5_000),
    });
    return resp.ok;
  } catch {
    return false;
  }
}

Type guard

export function isPetShareListError(error: unknown): boolean {
  return error instanceof Error && /petshare list page \d+ failed/.test(error.message);
}

Try / catch

try {
  const tasks = await listPetSharePets(limit);
} catch (error) {
  if (error instanceof Error && error.message.includes('petshare list page')) {
    // Transient — surface as partial failure, try hatchery instead
    syncResult.errors.push(error.message);
    const hatcheryTasks = await listHatcheryPets(limit);
    tasks.push(...hatcheryTasks);
  } else throw error;
}

Prevention

When it happens

Trigger: Calling the community pets sync (POST /api/codex-pets/sync with source 'petshare' or 'all') when the PetShare Supabase edge function returns 4xx/5xx. The fetch at line 115 gets a response, resp.ok is false, and the error is thrown at line 117.

Common situations: The PetShare Supabase function is rate-limited (429), under maintenance (503), or the function deployment is cold/timing out. A network proxy returns a 502. The PETSHARE_BASE URL has changed or the Supabase project is paused.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/12bccffe93a6f8a6. Report an issue: GitHub.