{"record":{"id":"2dfdb178011265c1","repo":"facebook/relay","slug":"normalizationengine-expected-path-for-stream-to","errorCode":null,"errorMessage":"NormalizationEngine: Expected path for @stream to end in a positive integer index, got `${String(finalPathEntry)}`","messagePattern":"NormalizationEngine: Expected path for @stream to end in a positive integer index, got `(.+?)`","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/relay-runtime/store/NormalizationEngine.js","lineNumber":513,"sourceCode":"\n    const prevIDs = RelayModernRecord.getLinkedRecordIDs(\n      parentRecord,\n      storageKey,\n    );\n    if (prevIDs == null) {\n      throw err(\n        'NormalizationEngine: Expected record `' +\n          parentID +\n          '` to have fetched field `' +\n          field.name +\n          '` with @stream.',\n      );\n    }\n\n    const finalPathEntry = path[path.length - 1];\n    const itemIndex = parseInt(finalPathEntry, 10);\n    if (itemIndex !== finalPathEntry || itemIndex < 0) {\n      throw err(\n        'NormalizationEngine: Expected path for @stream to end in a ' +\n          'positive integer index, got `' +\n          String(finalPathEntry) +\n          '`',\n      );\n    }\n\n    const typeName = field.concreteType ?? (data as $FlowFixMe).__typename;\n    if (typeof typeName !== 'string') {\n      throw err(\n        'NormalizationEngine: Expected @stream field `' +\n          field.name +\n          '` to have a __typename.',\n      );\n    }\n\n    const getDataID = this._options.getDataID;\n    const itemID =","sourceCodeStart":495,"sourceCodeEnd":531,"githubUrl":"https://github.com/facebook/relay/blob/668b1b85e06261aa3b58dabfc51f8b5524a70955/packages/relay-runtime/store/NormalizationEngine.js#L495-L531","documentation":"@stream payloads are identified by their position in a list; the last segment of the payload's path must be the integer index of the streamed item. Relay parses the final path entry and requires it to be a non-negative integer that round-trips (parseInt equal to the original). If the path ends in anything else (a field name, a string, -1), Relay cannot determine the list position and throws.","triggerScenarios":"Normalizing a @stream incremental payload whose `path` array does not end in a numeric index — e.g. a malformed incremental response from the server, a network layer that mangles the incremental path, or a custom router/gateway rewriting paths (string indices like \"01\" would also fail since parseInt yields 1 !== \"01\").","commonSituations":"Proxy or cache layers (e.g. persisted-query gateways, Cloudflare workers) re-serializing incremental delivery payloads, custom RelayNetwork implementations that build paths incorrectly, or testing harnesses fabricating incremental payloads with wrong paths.","solutions":["Inspect the incremental payload's `path` in your network layer; ensure the final element is the numeric list index","Fix or replace the middleware/proxy that is rewriting or dropping path segments","If building payloads in tests, construct path as [...fieldPath, itemIndex] with a real number as the last entry","Verify the server actually supports @stream/multipart incremental delivery and emits conformant paths"],"exampleFix":"// before\n{ path: [\"node\", \"comments\"] }\n// after\n{ path: [\"node\", \"comments\", 2] }","handlingStrategy":"validation","validationCode":"const last = payload.path[payload.path.length - 1];\nif (typeof last !== 'number' || !Number.isInteger(last) || last < 0) {\n  throw new Error(`Invalid @stream path terminator: ${String(last)}`);\n}","typeGuard":"function hasNumericIndexPath(p: unknown): p is (string | number)[] {\n  return Array.isArray(p) && typeof p[p.length - 1] === 'number' && Number.isInteger(p[p.length - 1]);\n}","tryCatchPattern":null,"preventionTips":["Validate incremental payload shape (label/path/id) in your network layer middleware","Avoid proxies that rewrite incremental delivery paths","Write conformant mock payloads in tests with numeric final path entries"],"tags":["relay","stream","incremental-delivery","path"],"backgroundTag":"relay-stream-normalization","analyzedSha":"668b1b85e06261aa3b58dabfc51f8b5524a70955","analyzedAt":"2026-09-02T19:57:20.783Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}