Runbook: Scanner — SBOM Generation Failures
Use this runbook when scans complete but SBOM generation, composition, or validation fails — leaving partial or missing components, schema-validation errors, or a degraded check.scanner.sbom success rate. It is written for the Platform on-call team. Because reachability analysis and SBOM-gated release promotions cannot proceed without a valid SBOM, treat these failures as release-blocking.
Stella Ops generates and validates SBOMs in two formats only — CycloneDX and SPDX. For related symptoms, see scanner-oom.mdand scanner-timeout.md.
Metadata
| Field | Value |
|---|---|
| Component | Scanner |
| Severity | High |
| On-call scope | Platform team |
| Last updated | 2026-05-30 |
| Doctor check | check.scanner.sbom |
Reconciled against
src/Scannerand the Doctor SBOM health check on 2026-05-30. The Doctor check ID ischeck.scanner.sbom(defined insrc/Doctor/__Plugins/StellaOps.Doctor.Plugin.Scanner/Checks/SbomGenerationHealthCheck.cs). Several CLI commands and config keys that earlier drafts of this runbook referenced are not implemented and have been removed or flagged inline.
Symptoms
- [ ] Scans completing but SBOM generation/composition failing
- [ ] Doctor check
check.scanner.sbomreporting Warn/Fail (success rate < 95% / < 80%) - [ ] SBOM validation failures reported by the Doctor check (
validation_failures > 0) - [ ] Error in scanner logs: “SBOM composition failed”, “unsupported”/“unknown package format”, schema validation errors
- [ ] Partial SBOM with missing components
NOTE (NOT IMPLEMENTED): there is no
ScannerSbomGenerationFailedPrometheus alert and noscanner_sbom_generation_failures_totalmetric in the codebase (src/anddevops/contain neither). Health is surfaced through the Doctor check above, not a dedicated alert/counter. If a Prometheus alert is required, track it as a follow-up rather than relying on it here.
Impact
| Impact Type | Description |
|---|---|
| User-facing | Incomplete vulnerability coverage; missing dependencies not scanned |
| Data integrity | Partial SBOM may miss vulnerabilities; attestations incomplete |
| Pipeline | Reachability analysis and SBOM-gated release promotions cannot proceed without a valid SBOM |
| SLA impact | SBOM generation success rate degraded (Doctor warns < 95%, fails < 80%) |
Diagnosis
Quick checks
Run the Doctor SBOM health check:
stella doctor --check check.scanner.sbom # or, explicitly via the run sub-command: stella doctor run --check check.scanner.sbomThis queries the Scanner service at
/api/v1/sbom/statsand reportstotal_generated,successful_generations,failed_generations,success_rate,format_cyclonedx,format_spdx, andvalidation_failures. The check needsScanner:Url(orServices:Scanner:Url) configured.NOTE: the Doctor check depends on the Scanner exposing
/api/v1/sbom/stats. That endpoint is not currently mapped inStellaOps.Scanner.WebService(only/api/v1/sbom/validate,/api/v1/sbom/validators,/api/v1/sbom/upload, and/api/v1/sbom/{scanId}/evidenceexist). If the check reports “Cannot retrieve SBOM stats”, treat the stats endpoint as a known gap and fall back to scanner logs below.Inspect scanner service logs for SBOM/composition failures:
docker compose -f devops/compose/docker-compose.stella-ops.yml logs scanner | grep -iE "sbom|composition|validation"Look for: composition/validation errors, unsupported format messages, out-of-memory or timeout signals during emit.
Check the scan status for the affected scan:
# GET /api/scans/{scanId} — returns status + failureReason curl -sS -H "Authorization: Bearer $TOKEN" \ https://stella-ops.local/api/scans/<scan-id> | jq '{status, failureReason}'The
failureReasonfield carries the recorded failure for the scan.
Deep diagnosis
Validate a specific SBOM document against the schemas:
# POST /api/v1/sbom/validate — validates against CycloneDX or SPDX schema curl -sS -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/vnd.cyclonedx+json" \ --data-binary @sbom.cdx.json \ "https://stella-ops.local/api/v1/sbom/validate"The response is an
SbomValidationResponseDto: checkisValid,errorCount/warningCount, and thediagnostics[]array — each diagnostic carriesseverity,code,message,path,line, andsuggestiondescribing the schema/format problem. (There is no top-levelerrors[]field on this endpoint; that key only appears on the BYOS upload’s 400 problem-details.) Requires thescanner.scans.readpolicy (scopescanner:read).NOTE: if the validation gate is disabled (
Enabled = falseorMode = Off), this endpoint short-circuits and returnsisValid: truewithvalidatorName: "validation-disabled"regardless of the document — so a “valid” result here does not prove the SBOM is well-formed. A503withvalidatorName/diagnostic codeVALIDATOR_UNAVAILABLEmeans the validator itself could not run.List available SBOM validators / supported formats:
# GET /api/v1/sbom/validators curl -sS -H "Authorization: Bearer $TOKEN" \ "https://stella-ops.local/api/v1/sbom/validators"Stella generates and validates two SBOM formats: CycloneDX and SPDX (
SbomFormats.CycloneDx/SbomFormats.Spdx). There is no third “generator” backend.Confirm language-analyzer plug-ins load and verify:
# Enumerates analyzer plug-ins under a directory and checks signatures. stella scanner plugins list <plugin-dir> stella scanner plugins verify --manifest <manifest-path>Problem if: an analyzer plug-in fails signature verification or is missing, so the corresponding ecosystem is not analyzed. (These commands operate on plug-in directories/manifests; there is no per-plugin enable/restart/log surface in the CLI.)
Resolution
Immediate mitigation
Restart the scanner to clear bad cached state:
docker compose -f devops/compose/docker-compose.stella-ops.yml restart scannerRe-run the scan once the underlying cause is addressed:
# POST /api/scans — resubmit the image (use force to bypass cached results) curl -sS -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"image":{"reference":"<image-ref>"},"force":true}' \ "https://stella-ops.local/api/scans"Requires the
scanner.apipolicy (scopescanner:scan).Supply a Bring-Your-Own-SBOM (BYOS) document for the scan when the built-in composition cannot complete and you have a trusted SBOM:
# POST /api/scans/{scanId}/sbom — accepts CycloneDX 1.6/1.7 or SPDX JSON curl -sS -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/vnd.cyclonedx+json; version=1.7" \ --data-binary @sbom.cdx.json \ "https://stella-ops.local/api/scans/<scan-id>/sbom"Requires the
scanner.scans.writepolicy (scopescanner:write). Accepted content types:application/vnd.cyclonedx+json(version 1.6/1.7),application/spdx+json,application/json.NOTE: a host-wide
--sbom-fallback/--sbom-partial-okflag and ansbom.fallback_modeconfig key do not exist. BYOS upload above is the supported way to substitute an SBOM.
Root cause fix
If an ecosystem is not analyzed (missing/failed analyzer plug-in):
Enumerate and verify the language-analyzer plug-ins:
stella scanner plugins list <plugin-dir> stella scanner plugins verify --manifest <manifest-path>Re-deploy the correct (signed) analyzer plug-in bundle and restart the scanner so the plug-in loader picks it up. Supported ecosystems include the OS package managers (apk, dpkg, rpm, pacman, portage, homebrew, etc.) and the language analyzers under
src/Scanner/StellaOps.Scanner.Analyzers.Lang.*.NOTE: the CLI has no
stella scanner plugins enable/restart/logsand no--type package-managerfilter, and there is nosbom.custom_mappings.<format>config key. Analyzer coverage is managed by deploying signed plug-in bundles, not by per-plugin CLI toggles.
If SBOM schema validation is failing:
- Validate the document to see the precise schema error (see Deep diagnosis step 1). The emit-side validation pipeline (
StellaOps.Scanner.Emit.Composition.SbomValidationPipeline) validates both CycloneDX and SPDX output;FailOnError(defaulttrue) means a failed validation aborts composition. - Correct the source artifact (truncated layers, malformed/missing manifests) or upgrade the scanner image so the generator and schema version match, then re-run the scan.
If source artifacts are corrupted:
- Re-pull or rebuild the image and confirm the digest matches what is being scanned (deployments pull by digest, not tag).
- Report unrecoverable layers to the image owner for a rebuild.
If memory exhaustion or timeout occurs during composition:
- Increase the scanner container memory and watch for OOM:
# devops/compose/docker-compose.stella-ops.yml services: scanner: deploy: resources: limits: memory: 4Gdocker compose -f devops/compose/docker-compose.stella-ops.yml up -d scanner - The SBOM validation pipeline has a default
ValidationTimeoutof 60s (SbomValidationPipelineOptions.ValidationTimeout). Very large images may exceed it; raise scanner resources or split the workload rather than relying on a per-command timeout flag (nosbom.timeout/sbom.streaming_modeconfig key exists).
Verification
# Re-run the Doctor SBOM health check
stella doctor run --check check.scanner.sbom
# Re-validate the produced SBOM against the schema
curl -sS -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/vnd.cyclonedx+json" \
--data-binary @sbom.cdx.json \
"https://stella-ops.local/api/v1/sbom/validate"
# Confirm the scan completed
curl -sS -H "Authorization: Bearer $TOKEN" \
https://stella-ops.local/api/scans/<scan-id> | jq '{status, failureReason}'
Prevention
- [ ] Plugins: Keep all language-analyzer plug-ins deployed, signed, and current
- [ ] Monitoring: Run
check.scanner.sbomregularly; it warns < 95% and fails < 80% success rate - [ ] Resources: Keep the
check.scanner.resourcesDoctor check green — resource exhaustion is a top cause of SBOM failures - [ ] Testing: Validate SBOM generation for new image/base-image types before production
Related Resources
- Doctor article:
docs/doctor/articles/scanner/sbom.md(companion tocheck.scanner.sbom) - Architecture:
docs/modules/scanner/deterministic-sbom-compose.md,docs/modules/scanner/signed-sbom-archive-spec.md - Related runbooks:
scanner-oom.md,scanner-timeout.md - Source of truth:
src/Scanner/__Libraries/StellaOps.Scanner.Emit/Composition/(SBOM composition + validation),src/Doctor/__Plugins/StellaOps.Doctor.Plugin.Scanner/Checks/SbomGenerationHealthCheck.cs
