Registry Referrer Discovery Troubleshooting
Source currency 2026-10-07: verified against
c0b0490da306d66a818486b09ae9fd440a3bda1b. Source placement and the scoped historical boundary below were rechecked. This document adds no deployment, completed CI, or runtime-acceptance claim. Re-verify:rg -n "Total.Add|AddOciReferrerDiscoveryService" src/OfflineKit/__Libraries/StellaOps.ExportCenter.Application/Distribution/Oci/OciReferrerDiscoveryService.csand the adjacent owner pointers below.
Audience: platform operators and SREs running Stella Ops mirror-bundle exports. Modules: OfflineKit export application and carrier/import libraries.
This runbook helps you diagnose and resolve OCI referrer discovery issues during mirror-bundle exports — when referrers (SBOMs, attestations, signatures) attached to a container image are not discovered, are only partially discovered, or fail validation on import. Start at Quick Reference to map a symptom to a likely cause, then drop into Diagnosing Issues for the detailed checks.
Quick Reference
| Symptom | Likely Cause | Solution |
|---|---|---|
| No referrers discovered | Registry doesn’t support referrers API | Check registry compatibility |
| Discovery timeout | Network issues or slow registry | Increase timeout, check connectivity |
| Partial referrers | Rate limiting or auth issues | Check credentials and rate limits |
| Checksum mismatch | Referrer modified after discovery | Re-export bundle |
Historical Registry Comparison (retained 2026-10-07; vendor capabilities unverified)
| Registry | OCI 1.1 API | Fallback | Notes |
|---|---|---|---|
| Docker Hub | Partial | Yes | Rate limits may affect discovery |
| GHCR | No | Yes | Uses tag-based discovery only |
| GCR | Yes | Yes | Full OCI 1.1 support |
| ECR | Yes | Yes | Requires proper IAM permissions |
| ACR | Yes | Yes | Full OCI 1.1 support |
| Harbor 2.0+ | Yes | Yes | Full OCI 1.1 support |
| Quay | Partial | Yes | Varies by version; admin toggles may control feature |
| JFrog Artifactory | Partial | Yes | Requires OCI layout repository |
| GitLab | No | Yes | Stores subject field but no referrers endpoint |
These vendor/version observations are retained history. Probe the actual registry and digest before choosing native or fallback discovery. Source parser success alone does not establish authorization, reachability, media type, or content identity.
Registry capability procedure
See Registry Compatibility Matrix for detailed information.
Diagnosing Issues
1. Check Export Logs
Look for capability probing and discovery logs:
# Look for probing logs
docker logs <offlinekit-instance> 2>&1 | grep "Probing.*registries for OCI referrer"
# Check individual registry results
docker logs <offlinekit-instance> 2>&1 | grep "Registry.*OCI 1"
# Example output:
# [INFO] Probing 2 registries for OCI referrer capabilities before export
# [INFO] Registry gcr.io: OCI 1.1 (referrers API supported, version=OCI-Distribution/2.1, probe_ms=42)
# [WARN] Registry ghcr.io: OCI 1.0 (using fallback tag discovery, version=registry/2.0, probe_ms=85)
2. Check Telemetry Metrics
Query Prometheus for referrer discovery metrics:
# Capability probes by registry and support status
# api_supported is the lowercased bool string "true" | "false"
sum by (registry, api_supported) (
rate(export_registry_capabilities_probed_total[5m])
)
# Discovery method breakdown (method = "native" | "fallback")
sum by (registry, method) (
rate(export_referrer_discovery_method_total[5m])
)
# Referrers discovered by artifact type (artifact_type = sbom|vex|attestation|other|unknown)
sum by (registry, artifact_type) (
rate(export_referrers_discovered_total[5m])
)
# Failure rate by registry (tagged with error_type)
sum by (registry, error_type) (
rate(export_referrer_discovery_failures_total[5m])
)
The four counter calls are implemented by OciReferrerDiscoveryService in src/OfflineKit/__Libraries/StellaOps.ExportCenter.Application/Distribution/Oci/OciReferrerDiscoveryService.cs (meter StellaOps.ExportCenter). The retained namespace does not identify a standalone ExportCenter host. These counters are emitted when the configured discovery service’s methods execute; definitions alone do not prove a live emitter or a completed discovery. The probe itself is delegated to OciReferrerFallback.ProbeCapabilitiesAsync, but the metric .Add() calls all live in OciReferrerDiscoveryService — OciReferrerFallback emits no telemetry of its own.
| Metric | Tags | Source |
|---|---|---|
export_registry_capabilities_probed_total | registry, api_supported | one per ProbeRegistryCapabilitiesAsync (probe delegated to the fallback service) |
export_referrer_discovery_method_total | registry, method | one per successful DiscoverReferrersAsync call |
export_referrers_discovered_total | registry, artifact_type | one per referrer found |
export_referrer_discovery_failures_total | registry, error_type | discovery error (discovery_failed or exception type name, lowercased) |
3. Test Registry Connectivity
Manually probe registry capabilities:
# Test OCI referrers API (OCI 1.1)
curl -H "Accept: application/vnd.oci.image.index.v1+json" \
"https://registry.example.com/v2/myrepo/referrers/sha256:abc123..."
# Expected responses (how Stella Ops interprets them):
# - 200 OK with manifest list: Registry supports referrers API (native discovery)
# - 404 Not Found with an OCI image-index body: API supported, just no referrers for this digest
# - 404 Not Found without an OCI index body: API NOT supported -> tag-based fallback
# - 405 Method Not Allowed: API NOT supported -> tag-based fallback
# - 501 Not Implemented: API NOT supported -> tag-based fallback
#
# NB: OciReferrerFallback.ProbeReferrersApiAsync treats only 501 / 405 as
# "not implemented" during the lightweight capability probe (it probes with a
# zero-digest against a synthetic repo). The doctor check below additionally
# inspects 404 bodies to distinguish "no referrers" from "no API".
# Check distribution version
curl -I "https://registry.example.com/v2/"
# Look for: OCI-Distribution-API-Version (or legacy Docker-Distribution-API-Version) header
# OCI 1.1+ in the version string => SupportsReferrersApi is short-circuited to true
4. Test Fallback Tag Discovery
If native API is not supported:
# List tags matching fallback pattern
curl "https://registry.example.com/v2/myrepo/tags/list" | \
jq '.tags | map(select(startswith("sha256-")))'
# Expected: Tags like "sha256-abc123.sbom", "sha256-abc123.att"
Common Issues and Solutions
Issue: “Failed to probe capabilities for registry”
Symptoms:
- Warning logs about probe failures
- Referrer discovery using fallback or skipped
Causes:
- Network connectivity issues
- Authentication failures
- Registry rate limiting
- TLS certificate issues
Solutions:
# Check network connectivity
curl -v "https://registry.example.com/v2/"
# Verify authentication
docker login registry.example.com
# Check TLS certificates
openssl s_client -connect registry.example.com:443 -servername registry.example.com
These probe/auth failures are about the registry credentials used by the export worker (configured via
OCI:*/Registry:*settings), not Stella’s own Authority scopes. For reference, the ExportCenter API scopes areexport.viewer(read runs/bundles),export.operator(run exports), andexport.admin; mirror import while sealed requiresairgap:import. (Source:StellaOps.Auth.Abstractions/StellaOpsScopes.cs.)
Issue: “No referrers found for image”
Symptoms:
- Discovery succeeds but returns empty list
- Bundle missing expected SBOMs/attestations
Causes:
- No referrers actually attached to image
- Referrers attached to different digest (tag vs digest mismatch)
- Referrers pruned by registry retention policy
Solutions:
# Verify referrers exist for the specific digest
crane manifest registry.example.com/repo@sha256:abc123 | \
jq '.subject.digest'
# List referrers using oras
oras discover registry.example.com/repo@sha256:abc123
# Check if referrers exist with different artifact types
curl "https://registry.example.com/v2/repo/referrers/sha256:abc123?artifactType=application/vnd.cyclonedx%2Bjson"
Carrier import failures
The consolidated OfflineKit carrier route is POST /api/offlinekit/v1/import. OfflineKitImportService reports carrier bundle/manifest digest mismatches as BUNDLE_DIGEST_MISMATCH/MANIFEST_DIGEST_MISMATCH; claimed part-byte mismatches report PART_DIGEST_MISMATCH. Failed quarantine bytes are deleted, not retained as a permanent rejected-bundle forensic record. Capture the response/log evidence and the original operator-controlled files; do not assume a rejected carrier has an import ledger entry. See the current import pipeline.
Historical referrer-validator diagnostic (retained 2026-10-07)
Symptoms:
- The import fails and is quarantined with reason
referrer-validation-failed:checksum_mismatch=N ImportValidatorlogsofflinekit.import.validation failed ... reason_code=REFERRER_VALIDATION_FAILED ... checksum_mismatch=N- Bundle verification fails
How it is detected:
ReferrerValidator.Validate(called byImportValidatoronly formirror-bundleandoffline-kitbundle types) recomputes SHA-256 over each declared referrer artifact and compares it to thesha256field in the manifestreferrerssection.- A mismatch produces a
ReferrerChecksumMismatchissue (Error severity); any Error (ReferrerMissing,ReferrerChecksumMismatch, orReferrerSizeMismatch) fails the import.OrphanedReferreris a Warning only and does not fail the import.
Causes:
- Referrer artifact modified after export
- Registry replaced artifact
- Bundle corruption during transfer
Solutions:
- Re-export the bundle to get fresh referrer content
- Verify bundle integrity:
sha256sum bundle.tgz - Check if referrer was intentionally updated upstream
- Inspect the quarantine record (the failed bundle is moved to quarantine with the full verification log) to see the expected vs. actual digest
Issue: Harbor UI shows referrers as “UNKNOWN” artifact type
Symptoms:
- Referrer artifacts (cosign signatures, SBOMs) appear as “UNKNOWN” in Harbor UI
- API-level discovery works correctly
Causes:
- Harbor UI mediaType classification lags API capabilities (especially around v2.15+)
- Custom artifact types not recognized by Harbor’s UI layer
Solutions:
- This is a Harbor-side UI classification issue; it does not affect Stella Ops referrer discovery or functionality
- Verify API-level discovery works:
curl -H "Accept: application/vnd.oci.image.index.v1+json" "https://harbor.example.com/v2/repo/referrers/sha256:..." - If needed, check Harbor release notes for mediaType classification updates
Issue: Quay referrers API returns inconsistent results
Symptoms:
- Referrer discovery works on Quay.io but not on self-hosted Quay
- Intermittent 404 or empty results from referrers endpoint
Causes:
- OCI Referrers API feature not enabled in self-hosted Quay deployment
- Quay admin toggles or deployment flags controlling the feature
Solutions:
- Verify the OCI Referrers API feature is enabled in Quay’s deployment configuration
- Check Quay admin console for referrers-related feature flags
- If the feature is disabled, Stella Ops automatically uses tag-based fallback; no action required
- Contact Quay administrator to enable the feature if native referrers discovery is preferred
Issue: Slow referrer discovery
Symptoms:
- Export takes much longer than expected
- Timeout warnings in logs
Causes:
- Large number of referrers per image
- Slow registry responses
- No capability caching (cache miss)
Solutions:
The former export.referrer_discovery.timeout_seconds and max_concurrent_discoveries example is not a bound current configuration contract. For a configured OCI distribution client, the source option is ExportCenter:Distribution:Oci:TimeoutSeconds (OciDistributionOptions). Confirm the consuming registration and client before changing it; this does not advertise a universal referrer-discovery concurrency or timeout knob.
Validation Commands
Inspect Bundle Referrers
The bundle manifest is JSON (manifest.json) with a referrers section (referrers.subjects[].artifacts[], each carrying digest, path, sha256, size, and optional artifactType). Referrer payloads live under referrers/.
# List referrer payloads in the bundle
tar -tzf bundle.tgz | grep "^referrers/"
# Dump the referrers section of the manifest
tar -xzf bundle.tgz -O manifest.json | jq '.referrers'
# Recompute a specific referrer checksum and compare to the declared sha256
tar -xzf bundle.tgz -O referrers/sha256-abc123/sha256-def456.json | sha256sum
CLI Validation
There is no dedicated --check-referrers flag; referrer validation runs automatically during import for mirror-bundle and offline-kit bundle types (see the checksum-mismatch issue above). The operator-facing commands are:
# Probe whether the configured registry supports the OCI 1.1 referrers API.
# Requires OCI:RegistryUrl (or Registry:Url) to be configured; optional
# OCI:TestRepository (default library/alpine) and OCI:TestTag (default latest).
# (Source: RegistryReferrersApiCheck, CheckId "check.integration.oci.referrers".)
stella doctor --check check.integration.oci.referrers
# Broader registry capability matrix (referrers API + chunked upload, cross-repo
# mount, manifest/blob delete) reported as a capability_score like "3/5".
# (Source: RegistryCapabilityProbeCheck, CheckId "check.integration.oci.capabilities".)
stella doctor --check check.integration.oci.capabilities
# Verify an exported evidence bundle. Checks the manifest, artifact checksums,
# DSSE signatures, Rekor inclusion proofs, expected payload types, and (with
# --replay) large-blob content. NB: DSSE signatures are only *cryptographically*
# verified when --trust-root is supplied; without it they are presence-checked
# and reported as a warning. --strict fails on any warning (e.g. missing optional
# artifacts); --offline runs with no network access.
# (Source: BundleVerifyCommand, the `verify` subcommand of `stella bundle`.)
stella bundle verify --bundle bundle.tar.gz --strict
stella bundle verify --bundle bundle.tar.gz --offline
Note: the CLI binary is invoked as
stella. There is nostella bundle validateorstella bundle importsubcommand; the onlystella bundlesubcommand isverify(registered byBundleCommandGroup). An evidence-bundle verify is also reachable asstella verify bundle, a separate command that does not run referrer validation. The ImportValidator referrer diagnostic above is library-level predecessor behavior. Current carrier ingress usesstella airgap importand the OfflineKit custody route; it has its own signed-carrier and part-digest validation.
Escalation
If issues persist after following this runbook:
Run the built-in registry diagnostics and capture their evidence blocks:
stella doctor --check check.integration.oci.referrers(reportsregistry_url,api_endpoint,http_status,oci_version,referrers_supported, andfallback_required; emits a Warn result with afallback_patternofsha256-{digest}.{artifactType}when the API is absent)stella doctor --check check.integration.oci.capabilities(broader matrix:supports_referrers_api,supports_chunked_upload,supports_cross_repo_mount,supports_manifest_delete,supports_blob_delete, and an aggregatecapability_score)
Collect diagnostic information:
- Export logs with DEBUG level enabled
- Telemetry metrics for the affected time window
- Registry type and version
- Network trace if applicable
Search the issue tracker for known issues tagged
referrer-discovery.Open a support ticket with:
- Environment details (Stella Ops version, registry type)
- Error messages and logs
- Steps to reproduce
Related Documentation
- OfflineKit Architecture
- Registry Compatibility Matrix
- Offline Bundle Format
