Hmbown/CodeWhale · error · Error

Invalid local connection file.

Error message

Invalid local connection file.

What it means

Thrown when a file chosen via the `join-shared` input exceeds 4096 bytes. A local connection descriptor must be a tiny JSON file, so oversized files are rejected before parsing as a cheap guard against picking the wrong file.

Solutions

  1. Select the actual small connection descriptor file (a few hundred bytes of JSON) generated by the local server.
  2. Re-download or re-generate the connection file from the serving instance.
  3. Check the file size before import: it must be <= 4096 bytes.

Example fix

// before
const file = input.files[0]; // 5 MB replay file
// after
if (file.size > 4096) { alert('Pick the small connection file, not a replay.'); return; }
Defensive patterns

Strategy: validation

Validate before calling

if (file.size > 4096) { alert('That is not a connection file (too large).'); return; }

Type guard

null

Try / catch

try { joinShared(file); } catch (e) { showMessage(e.message); } finally { input.value = ''; }

Prevention

When it happens

Trigger: Selecting a large file (e.g. a replay JSON, log, or image) in the join-shared file picker instead of the small connection descriptor.

Common situations: Users confusing the replay export file with the connection file; OS dialog defaulting to the wrong directory.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/949e946f59b61c67. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/ui/pet.ts:312

      if (h.source === 'replay') {
        mode.querySelector<HTMLOptionElement>('[value="replay"]')!.disabled = false;
      }
      message.textContent = 'Restoring the saved habitat…';
      if (h.checkpoint && h.still === motion.checked) adoptWorld(savedWorld);
      else await rebuild(h.seconds, undefined, savedWorld.recording(false).start);
      message.textContent = 'Habitat restored locally. Sound starts only when you enable it.';
    } else await rebuild();
    persistenceReady = true; void refreshArchives().catch(() => {});
  } catch (error) { persistenceFailed = true; get('persistence').textContent = error instanceof Error ? error.message : 'Local persistence is unavailable.'; await rebuild(); }
  void refreshArchives().catch(() => {});
  setInterval(() => { void persist(); }, 5000); requestAnimationFrame(animate);
} catch (error) { message.textContent = error instanceof Error ? error.message : 'Unable to start the habitat.'; }

// Joining is a view switch; existing IndexedDB recordings are retained.
get<HTMLInputElement>('join-shared').onchange = async event => {
  const input = event.target as HTMLInputElement, file = input.files?.[0]; if (!file) return;
  try {
    if (file.size > 4096) throw new Error('Invalid local connection file.');
    const d = JSON.parse(await file.text());
    if (d.version !== 1 || !Number.isSafeInteger(d.port) || d.port < 1 || d.port > 65535 || !/^[a-f0-9]{64}$/i.test(d.token)) throw new Error('Invalid local connection file.');
    if (!await mayLeave()) return;
    location.assign(`http://127.0.0.1:${d.port}/#${d.token}`);
  } catch (e) { message.textContent = e instanceof Error ? e.message : 'Unable to attach.'; }
  finally { input.value = ''; }
};

View on GitHub (pinned to 433685b202)