apache/beam · error

unable to rewrite coder

Error message

unable to rewrite coder %v for timer %v for transform %v in stage %v: %w

What it means

Prism's buildDescriptor rewrites unknown coders on timer family declarations of a ParDo transform so the stage's bundle carries concrete coder bytes. When lpUnknownCoders fails to resolve or encode the timer family coder, this error wraps the underlying reason (unknown coder ID, missing component coder, unsupported URN) with the timer, transform and stage context. It means the pipeline's coder graph is incomplete or malformed for that timer.

Solutions

  1. Inspect the wrapped %w error to find which coder URN or component ID is unknown
  2. Verify the transform's timer family coder exists in components.coders of the submitted pipeline
  3. Regenerate the pipeline with a Beam SDK version compatible with the prism runner
  4. Check cross-language expansion output for coders not registered in the Go runner

Example fix

// before: timer coder references unknown id
v.TimerFamilyCoderId = "coder_missing"
// after: ensure the coder is registered in pipeline components before submit
pcoli.CoderId = registerKnownCoder(p, MyTimerType{}) // id resolvable via lpUnknownCoders
Defensive patterns

Strategy: validation

Validate before calling

// Before submitting, verify timer family coder is registered
if _, ok := comps.GetCoders()[timerFamilyCoderID]; !ok {
    return fmt.Errorf("timer family coder %q not registered", timerFamilyCoderID)
}

Try / catch

if err := submitPipeline(ctx, p); err != nil {
    var coderErr *CoderRewriteError
    if errors.As(err, &coderErr) { log.Fatalf("coder rewrite failed: %v", coderErr) }
    return err
}

Prevention

When it happens

Trigger: A ParDo transform in the stage declares a timer family whose TimerFamilyCoderId references a coder not present/known in components, or lpUnknownCoders fails while substituting a portable coder for an unknown one.

Common situations: SDK-generated pipelines with custom coders the runner hasn't seen; cross-language pipelines where a Python/Java SDK emits timer coders Go prism can't resolve; hand-crafted or truncated pipeline protobufs; Beam SDK/runner version mismatches introducing new coder URNs.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/ff851d3ac6cc8746. Report an issue: GitHub.

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/stage.go:529

			case *pipepb.StateSpec_ReadModifyWriteSpec:
				rewriteCoder(&s.ReadModifyWriteSpec.CoderId)
			}
			if rewriteErr != nil {
				return rewriteErr
			}
		}
		for timerID, v := range pardo.GetTimerFamilySpecs() {
			stg.hasTimers = append(stg.hasTimers, engine.StaticTimerID{TransformID: tid, TimerFamily: timerID})
			if v.TimeDomain == pipepb.TimeDomain_PROCESSING_TIME {
				if stg.processingTimeTimers == nil {
					stg.processingTimeTimers = map[string]bool{}
				}
				stg.processingTimeTimers[timerID] = true
			}
			rewrite = true
			newCid, err := lpUnknownCoders(v.GetTimerFamilyCoderId(), coders, comps.GetCoders())
			if err != nil {
				return fmt.Errorf("unable to rewrite coder %v for timer %v for transform %v in stage %v: %w", v.GetTimerFamilyCoderId(), timerID, tid, stg.ID, err)
			}
			v.TimerFamilyCoderId = newCid
		}
		if rewrite {
			pyld, err := proto.MarshalOptions{}.Marshal(pardo)
			if err != nil {
				return fmt.Errorf("unable to encode ParDoPayload for %v in stage %v after rewrite", tid, stg.ID)
			}
			t.Spec.Payload = pyld
		}
	}
	if len(transforms) == 0 {
		return fmt.Errorf("buildDescriptor: invalid stage - no transforms at all %v", stg.ID)
	}

	// Start with outputs, since they're simple and uniform.
	sink2Col := map[string]string{}
	col2Coders := map[string]engine.PColInfo{}

View on GitHub (pinned to 12126d8942)