{"record":{"id":"5614c0ec76144796","repo":"jlcodes99/cockpit-tools","slug":"invalid-bundle-platforms","errorCode":"invalid_bundle_platforms","errorMessage":"invalid_bundle_platforms","messagePattern":"invalid_bundle_platforms","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/accountTransferService.ts","lineNumber":344,"sourceCode":"}\n\nfunction parseAccountTransferBundle(jsonContent: string): Record<PlatformId, AccountTransferPlatformPayload> {\n  const parsed = parseJsonOrThrow(jsonContent, 'invalid_json');\n  if (!isRecord(parsed)) {\n    throw new Error('invalid_bundle_root');\n  }\n\n  if (parsed.schema !== ACCOUNT_TRANSFER_SCHEMA) {\n    throw new Error('invalid_bundle_schema');\n  }\n\n  if (parsed.version !== ACCOUNT_TRANSFER_VERSION) {\n    throw new Error('invalid_bundle_version');\n  }\n\n  const rawPlatforms = parsed.platforms;\n  if (!isRecord(rawPlatforms)) {\n    throw new Error('invalid_bundle_platforms');\n  }\n\n  const platforms: Record<PlatformId, AccountTransferPlatformPayload> = {} as Record<\n    PlatformId,\n    AccountTransferPlatformPayload\n  >;\n\n  for (const platform of ALL_PLATFORM_IDS) {\n    const resolved = resolvePlatformPayload(rawPlatforms[platform]);\n    platforms[platform] =\n      resolved ??\n      ({\n        account_count: 0,\n        exported_data: [],\n      } as AccountTransferPlatformPayload);\n  }\n\n  return platforms;","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/services/accountTransferService.ts#L326-L362","documentation":"The transfer bundle lacks a valid 'platforms' object. After schema and version checks pass, the importer requires parsed.platforms to be a record mapping platform IDs to payloads; anything else is rejected.","triggerScenarios":"parsed.version matches but isRecord(parsed.platforms) is false — platforms key missing, null, an array, or a non-object value.","commonSituations":"Bundles exported with no platform data, hand-edited files where platforms was deleted or renamed, exporting an empty selection and serializing it as null.","solutions":["Add a 'platforms' object keyed by platform ID (may be empty {} if intentional) to the bundle","Re-export the bundle ensuring at least the platforms wrapper is serialized","Fix renames like 'platform' back to 'platforms'","Validate the bundle structure against the AccountTransferBundle type before importing"],"exampleFix":"// before\n{ \"schema\": \"...\", \"version\": 1 }\n// after\n{ \"schema\": \"...\", \"version\": 1, \"platforms\": {} }","handlingStrategy":"validation","validationCode":"const obj = JSON.parse(text);\nif (typeof obj.platforms !== 'object' || obj.platforms === null || Array.isArray(obj.platforms)) {\n  throw new Error('invalid_bundle_platforms');\n}","typeGuard":"function hasPlatforms(v: unknown): v is { platforms: Record<string, unknown> } {\n  return typeof v === 'object' && v !== null && !Array.isArray(v)\n    && typeof (v as any).platforms === 'object' && (v as any).platforms !== null\n    && !Array.isArray((v as any).platforms);\n}","tryCatchPattern":"try {\n  await importBundle(text);\n} catch (e) {\n  if (e instanceof Error && e.message === 'invalid_bundle_platforms') {\n    alert('Bundle is missing a valid platforms object.');\n  } else throw e;\n}","preventionTips":["Always include the platforms object in exports, even when empty ({})","Do not rename platforms to platform or move payloads to the root","Round-trip exports through the app's importer in tests to catch shape drift","Validate bundles with a JSON schema before import"],"tags":["validation","json","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}