apache/beam · critical

stage[ ] no parent ID for side input

Error message

stage[%v] no parent ID for side input %v

What it means

Before a stage with side inputs can run, Prism checks readiness by looking up each side input's parent PCollection in em.pcolParents. If a side input's PCollection has no registered parent stage, the pipeline graph is inconsistent — the side input cannot be evaluated because its producing stage is unknown. The runner panics naming the stage and the side input.

Solutions

  1. Check how the side input PCollection is produced; ensure it comes from a materializable transform (e.g. an explicit GBK or DoFn stage)
  2. Try materializing the side input with an intermediate identity transform or GBK so prism registers a parent stage
  3. Simplify or replace exotic side-input patterns (e.g. side inputs of side inputs) with supported ones
  4. Upgrade to the latest Beam version; prism side-input handling has improved over releases
  5. If it persists, file an issue with the pipeline graph — this indicates a prism translation bug

Example fix

// before: side input from a transform prism cannot parent
side := beam.SideInput{Input: viewOfUnmaterializedPColl}
// after: force materialization via a view over a GBK-backed PCollection
sideInput := beam.SideInput{Input: view.AsList(s, materializedPColl)}
Defensive patterns

Strategy: fallback

Validate before calling

if _, ok := pcolParents[side.Global]; !ok {
    return fmt.Errorf("side input %v has no producing stage registered", side.Global)
}

Prevention

When it happens

Trigger: em.pcolParents lacks an entry for side.Global when checking side-input readiness, i.e. the PCollection feeding the side input was never registered as the output of a stage — usually a pipeline-construction/translation bug or an unsupported side-input wiring pattern.

Common situations: Side inputs whose producing transform was fused away or not materialized, AsView/View.AsMap usages on PCollections that prism failed to link, cross-language pipeline fragments where the side input producer lives in another runner component.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/runners/prism/internal/engine/elementmanager.go:2596

	case isStatefulStage && len(ss.sides) == 0 && em.sawResidual.Load() && ss.hasBuildableDataLocked(upstreamW):
		// A stateful stage processes pending data at whatever the current
		// watermark is, so data alone makes it ready once something is self
		// checkpointing. Side input readiness comes from the watermark, so
		// stages that read one keep waiting.
	case inputW == upstreamW && previousInputW == inputW:
		// Otherwise, use the progression of watermark to determine the bundle readiness.
		slog.Debug("bundleReady: unchanged upstream watermark",
			slog.String("stage", ss.ID),
			slog.Group("watermark",
				slog.Any("upstream == input == previousInput", inputW)))
		return mtime.MinTimestamp, false, ptimeEventsReady, injectedReady
	}

	ready := true
	for _, side := range ss.sides {
		pID, ok := em.pcolParents[side.Global]
		if !ok {
			panic(fmt.Sprintf("stage[%v] no parent ID for side input %v", ss.ID, side))
		}
		parent, ok := em.stages[pID]
		if !ok {
			panic(fmt.Sprintf("stage[%v] no parent for side input %v, with parent ID %v", ss.ID, side, pID))
		}
		ow := parent.OutputWatermark()
		if upstreamW > ow {
			ready = false
		}
	}
	return upstreamW, ready, ptimeEventsReady, injectedReady
}

// processingTimeNow gives the current processing time for the runner.
func (em *ElementManager) processingTimeNow() (ret mtime.Time) {
	if em.testStreamHandler != nil && !em.testStreamHandler.completed {
		return em.testStreamHandler.Now()
	}

View on GitHub (pinned to 12126d8942)