koala73/worldmonitor · error · Error

Invalid PortWatch seed metadata

Error message

Invalid PortWatch seed metadata

What it means

After loading the canonical snapshot the script reads its seed metadata snapshot (META_KEY) in strict mode. If metadata exists but is not a plain object (e.g. an array, string, or number), the script throws 'Invalid PortWatch seed metadata' rather than run with corrupt bookkeeping data.

Solutions

  1. Delete the META_KEY snapshot so the seed recreates metadata on the next run
  2. Rewrite META_KEY with the expected plain-object shape (matching the current script's writer)
  3. Check for interrupted prior seed runs and re-run the full seed to regenerate both snapshots
  4. Confirm no other job writes to META_KEY with a different format

Example fix

// before (invalid array metadata)
["generatedAt", "count"]
// after
{ "generatedAt": "2026-09-15T00:00:00Z", "count": 42 }
Defensive patterns

Strategy: validation

Validate before calling

const meta = await readSeedSnapshot(META_KEY, { strict: false });
if (meta !== null && (typeof meta !== 'object' || Array.isArray(meta))) {
  await clearSeedSnapshot(META_KEY);
}

Type guard

const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);

Try / catch

try {
  await runSeed();
} catch (err) {
  if (err.message === 'Invalid PortWatch seed metadata') {
    await resetMetaSnapshot();
    await runSeed();
  } else throw err;
}

Prevention

When it happens

Trigger: readSeedSnapshot(META_KEY, { strict: true }) returns a non-null value that is not a plain object: an array, primitive, or otherwise malformed metadata persisted by a prior run or written out-of-band.

Common situations: Metadata overwritten by a tool that wrote a JSON array; partial/corrupt write from an interrupted seed; schema drift where a newer script stores a different metadata shape; manual edits to seed state.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/460f3b3ade40fa18. Report an issue: GitHub.

Appendix: source

Thrown at scripts/seed-portwatch-port-activity.mjs:1744

        canonicalAdvances: false,
        metaPayload: buildPortActivityFailureMeta(previousMeta, { reason: new Error('SIGTERM') }),
      });
    } catch {}
    try { await releaseLock(LOCK_DOMAIN, runId); } catch {}
    process.exit(1);
  };
  process.on('SIGTERM', onSigterm);
  process.on('SIGINT', onSigterm);

  try {
    const prevIso2List = await readSeedSnapshot(CANONICAL_KEY, { strict: true });
    previousMeta = await readSeedSnapshot(META_KEY, { strict: true });
    if (prevIso2List !== null && (!Array.isArray(prevIso2List)
      || prevIso2List.some((iso2) => typeof iso2 !== 'string' || !/^[A-Z]{2}$/.test(iso2)))) {
      throw new Error('Invalid PortWatch canonical snapshot');
    }
    if (previousMeta !== null && (typeof previousMeta !== 'object' || Array.isArray(previousMeta))) {
      throw new Error('Invalid PortWatch seed metadata');
    }
    previousRead = true;
    prevCountryKeys = Array.isArray(prevIso2List) ? prevIso2List.map(iso2 => `${KEY_PREFIX}${iso2}`) : [];

    console.log(`  Fetching port activity data (60d: last30 + prev30 windows)...`);
    const {
      countries,
      countryData,
      servedStaleCount,
      droppedTooOldCount,
      droppedNoCacheCount,
      freshFetchedCount,
      cacheHitCount,
      retryState,
      coverage,
    } = await fetchAll(progress, {
      signal: shutdownController.signal,
      expectedCountries: Array.isArray(prevIso2List) ? prevIso2List : [],

View on GitHub (pinned to 7d06c8633d)