{"record":{"id":"9f9f10930ca0a9d8","repo":"apache/beam","slug":"unknown-output-tag-s","errorCode":null,"errorMessage":"Unknown output tag %s","messagePattern":"Unknown output tag (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/harness/src/main/java/org/apache/beam/fn/harness/FnApiDoFnRunner.java","lineNumber":1646,"sourceCode":"      }\n\n      @Override\n      public PipelineOptions getPipelineOptions() {\n        return pipelineOptions;\n      }\n\n      @Override\n      public void output(OutputT output, Instant timestamp, BoundedWindow window) {\n        outputTo(\n            mainOutputConsumer, WindowedValues.of(output, timestamp, window, PaneInfo.NO_FIRING));\n      }\n\n      @Override\n      public <T> void output(TupleTag<T> tag, T output, Instant timestamp, BoundedWindow window) {\n        FnDataReceiver<WindowedValue<T>> consumer =\n            (FnDataReceiver) localNameToConsumer.get(tag.getId());\n        if (consumer == null) {\n          throw new IllegalArgumentException(String.format(\"Unknown output tag %s\", tag));\n        }\n        outputTo(consumer, WindowedValues.of(output, timestamp, window, PaneInfo.NO_FIRING));\n      }\n    }\n\n    private final FinishBundleArgumentProvider.Context context =\n        new FinishBundleArgumentProvider.Context();\n\n    @Override\n    public DoFn<InputT, OutputT>.FinishBundleContext finishBundleContext(\n        DoFn<InputT, OutputT> doFn) {\n      return context;\n    }\n\n    @Override\n    public PipelineOptions pipelineOptions() {\n      return pipelineOptions;\n    }","sourceCodeStart":1628,"sourceCodeEnd":1664,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/harness/src/main/java/org/apache/beam/fn/harness/FnApiDoFnRunner.java#L1628-L1664","documentation":"Thrown by the bundle-context OutputReceiver (used for FinishBundle/StartBundle emissions) when MultiOutputReceiver.output is called with a TupleTag whose id has no registered consumer in localNameToConsumer. The tag must correspond to an output declared in the PCollection/PCollectionTuple wired into the pipeline step.","triggerScenarios":"Calling context.output(tag, output, timestamp, window) (FinishBundleArgumentProvider.Context) with a TupleTag that is not among the transform's declared outputs; building the TupleTag with a different id string than the one registered for the output PCollection.","commonSituations":"Multi-output DoFns emitting to a tag created with `new TupleTag<>(){}` where a new anonymous instance differs from the registered one; typos in tag names; emitting from @FinishBundle to a tag not declared in PCollectionTuple; DoFn refactor adding outputs without updating the tuple registration.","solutions":["Register the TupleTag in the PCollectionTuple/apply call that declares the transform's outputs (withOutputTag) before emitting to it.","Reuse the exact same TupleTag instance (or same id) for both registration and emission — create them as static final constants.","Log available output tag ids and compare with the tag being used to spot id mismatches.","If the tag is intentionally absent (conditional outputs), guard the emission with a check that the output was declared."],"exampleFix":"// before\nTupleTag<String> extra = new TupleTag<String>() {}; // new instance, different id\nc.output(extra, value);\n\n// after\nprivate static final TupleTag<String> EXTRA_TAG = new TupleTag<String>() {};\n// register: tuple.withOutputTag(EXTRA_TAG, ...)\nc.output(EXTRA_TAG, value);","handlingStrategy":"validation","validationCode":"Set<String> declaredTags = tuple.getAllTags().stream().map(TupleTag::getId).collect(Collectors.toSet());\nif (!declaredTags.contains(tag.getId())) {\n  throw new IllegalArgumentException(\"Undeclared output tag: \" + tag.getId());\n}","typeGuard":null,"tryCatchPattern":"try {\n  ctx.output(tag, value);\n} catch (IllegalArgumentException e) {\n  logger.error(\"Tag {} not registered; declared: {}\", tag, declaredTags, e);\n}","preventionTips":["Use static final TupleTag constants shared between registration and emission","Register every emitted tag via withOutputTags/withOutputTag","Add a pipeline-construction unit test that exercises all outputs"],"tags":["beam","output-tag","multi-output","illegal-argument"],"backgroundTag":"resource-not-found","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"}