{"record":{"id":"57e2ed40387d5656","repo":"apache/beam","slug":"missing-non-side-input","errorCode":null,"errorMessage":"Missing non-side input.","messagePattern":"Missing non-side input\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/typescript/src/apache_beam/runners/direct_runner.ts","lineNumber":339,"sourceCode":"  for (const [transformId, transform] of Object.entries(transforms)) {\n    if (\n      transform.spec?.urn === parDo.urn &&\n      Object.keys(transform.inputs).length > 1\n    ) {\n      const spec = runnerApi.ParDoPayload.fromBinary(transform.spec!.payload);\n\n      // Figure out which input is the main input.\n      // TODO: (Typescript) Is there a clean way to do a set difference?\n      // There is a proposal for Set.prototype.intersect: https://github.com/tc39/proposal-set-methods\n      // But I don't think there is a nicer way at the moment.\n      let mainPCollTag: string = undefined!;\n      for (const tag of Object.keys(transform.inputs)) {\n        if (!spec.sideInputs[tag]) {\n          if (mainPCollTag) throw new Error(\"Multiple non-side inputs.\");\n          mainPCollTag = tag;\n        }\n      }\n      if (!mainPCollTag) throw new Error(\"Missing non-side input.\");\n\n      // Add the extra logic for each of the side inputs.\n      const bufferInputs = { mainPCollTag: transform.inputs[mainPCollTag] };\n      for (const side of Object.keys(spec.sideInputs)) {\n        const sidePCollId = transform.inputs[side];\n        const sideCopyId = uniqueName(pcolls, sidePCollId + \"-\" + side);\n        pcolls[sideCopyId] = pcolls[sidePCollId];\n        transform.inputs[side] = sideCopyId;\n        const controlPCollId = uniqueName(\n          pcolls,\n          sidePCollId + \"-\" + side + \"-control\",\n        );\n        pcolls[controlPCollId] = pcolls[transform.inputs[mainPCollTag]];\n        bufferInputs[side] = controlPCollId;\n        const collectTransformId = uniqueName(\n          transforms,\n          transformId + \"-\" + side + \"-collect\",\n        );","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/typescript/src/apache_beam/runners/direct_runner.ts#L321-L357","documentation":"The counterpart of the multiple-main-input check: after scanning transform.inputs, if no non-side input was found (every input is declared a side input), rewriteSideInputs throws 'Missing non-side input.' A side-input-consuming transform must have exactly one main input to buffer against.","triggerScenarios":"Applying a DoFn whose inputs map contains only tags present in spec.sideInputs — e.g. calling the transform with no main PCollection input, or mistakenly registering the main input as a side input.","commonSituations":"Incorrect sideInputs registration where the primary PCollection was added via the side-input API; constructing the transform programmatically and forgetting the main input; wiring bugs in custom composites.","solutions":["Pass the main PCollection as a regular input (not via the side-input helper).","Remove the main input's tag from spec.sideInputs so it is recognized as the main input.","Verify the inputs map: exactly one key must be absent from spec.sideInputs."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const mainInputs = Object.keys(transform.inputs).filter(t => !spec.sideInputs[t]);\nif (mainInputs.length === 0) throw new Error('Transform needs a main (non-side) input');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass the primary PCollection as a normal input, never via the side-input helper.","Double-check sideInputs registration lists only auxiliary inputs.","Write a unit test asserting exactly one main input per side-input transform."],"tags":["side-inputs","pardo","direct-runner","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}