## TL;DR

## Proposed Solution Extend the same `generateName`-sanitization logic from #9826 (currently only applied in the `PipelineSpec` branch) into the `PipelineRef.Resolver` branch, keeping the existing cluster-resolver `kind=pipeline` override as a higher-priority path since it already yields a correct, stable name when present. Concretely, in `pkg/reconciler/pipelinerun/pipelinerun.go`: ``` func propagatePipelineNameLabelToPipelineRun(pr *v1.PipelineRun) error { if pr.ObjectMeta.Labels == nil { pr.ObjectMeta.Labels = make(map[string]string) } if _, ok := pr.ObjectMeta.Labels[pipeline.PipelineLabelKey]; ok { return nil } switch { case pr.Spec.PipelineRef != nil && pr.Spec.PipelineRef.Name != "": pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = pr.Spec.PipelineRef.Name case pr.Spec.PipelineSpec != nil: pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = sanitizedPipelineRunName(pr) case pr.Spec.PipelineRef != nil && pr.Spec.PipelineRef.Resolver != "": // Default: sanitized generateName (or full name if generateName is absent), // mirroring the PipelineSpec branch's cardinality-reduction behavior. pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = sanitizedPipelineRunName(pr) // https://tekton.dev/docs/pipelines/cluster-res

[mathur07]: ## Proposed Solution Extend the same `generateName`-sanitization logic from #9826 (currently only applied in the `PipelineSpec` branch) into the `PipelineRef.Resolver` branch, keeping the existing cluster-resolver `kind=pipeline` override as a higher-priority path since it already yields a correct, stable name when present. Concretely, in `pkg/reconciler/pipelinerun/pipelinerun.go`: ``` func propagatePipelineNameLabelToPipelineRun(pr *v1.PipelineRun) error { if pr.ObjectMeta.Labels == nil { pr.ObjectMeta.Labels = make(map[string]string) } if _, ok := pr.ObjectMeta.Labels[pipeline.PipelineLabelKey]; ok { return nil } switch { case pr.Spec.PipelineRef != nil && pr.Spec.PipelineRef.Name != "": pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = pr.Spec.PipelineRef.Name case pr.Spec.PipelineSpec != nil: pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = sanitizedPipelineRunName(pr) case pr.Spec.PipelineRef != nil && pr.Spec.PipelineRef.Resolver != "": // Default: sanitized generateName (or full name if generateName is absent), // mirroring the PipelineSpec branch's cardinality-reduction behavior. pr.ObjectMeta.Labels[pipeline.PipelineLabelKey] = sanitizedPipelineRunName(pr) // https://tekton.dev/docs/pipelines/cluster-res

Context: GitHub issue tektoncd/pipeline#10686 (open, 3 comments, reported 2026-09-01): ## Expected Behavior For a PipelineRun that references its Pipeline via a resolver (git, bundle, hub, etc.), the `pipeline` label on `tekton_pipelines_controller_pipelinerun_*` / `tekton_pipelines_controller_taskrun_*` metrics should reflect a stable identifier for the pipeline (e.g. derived from `generateName`, matching the fix applied in #9826 for inline `PipelineSpec`), so that all runs of the same pipeline aggregate under the same metric series. ## Actual Behavior For any `pipelineRef.resolver` other than `cluster` (i.e. `git`, `bundle`, `hub`), `propagatePipelineNameLabelToPipelineRun`

## Matched source
Source: GitHub issue: https://github.com/tektoncd/pipeline/issues/10686
Original query: "Resolver-based PipelineRef still causes unbounded pipeline label cardinality (gap left by #9826)"
Key terms: 9826, based, cardinality, causes, label, left, pipeline, pipelineref, resolver, still, unbounded

## When to use

- You hit this exact issue.
- The symptom matches: Resolver-based PipelineRef still causes unbounded pipeline label cardinality (gap left by #9826).

## When NOT to use

- A different error or symptom; the cause here is specific to this one.

## Compatibility

Per the linked source.

## Edge cases

- If your error message differs even slightly, this is probably a different issue; search the exact text.
- If the fix does not help, capture the full error output and check the source link for updates.

## Source

GitHub issue: https://github.com/tektoncd/pipeline/issues/10686