{"record":{"id":"998bae43aeb1293f","repo":"GoogleContainerTools/jib","slug":"blob-not-available-for-digest-only-layer","errorCode":null,"errorMessage":"Blob not available for digest-only layer","messagePattern":"Blob not available for digest-only layer","errorType":"exception","errorClass":"LayerPropertyNotFoundException","httpStatus":null,"severity":"error","filePath":"jib-core/src/main/java/com/google/cloud/tools/jib/image/DigestOnlyLayer.java","lineNumber":40,"sourceCode":"\n/** A {@link Layer} reference that only has its {@link DescriptorDigest}. */\npublic class DigestOnlyLayer implements Layer {\n\n  /** The {@link BlobDescriptor} of the compressed layer content. */\n  private final BlobDescriptor blobDescriptor;\n\n  /**\n   * Instantiate with a {@link DescriptorDigest}.\n   *\n   * @param digest the digest to instantiate the {@link DigestOnlyLayer} from\n   */\n  public DigestOnlyLayer(DescriptorDigest digest) {\n    blobDescriptor = new BlobDescriptor(digest);\n  }\n\n  @Override\n  public Blob getBlob() throws LayerPropertyNotFoundException {\n    throw new LayerPropertyNotFoundException(\"Blob not available for digest-only layer\");\n  }\n\n  @Override\n  public BlobDescriptor getBlobDescriptor() {\n    return blobDescriptor;\n  }\n\n  @Override\n  public DescriptorDigest getDiffId() throws LayerPropertyNotFoundException {\n    throw new LayerPropertyNotFoundException(\"Diff ID not available for digest-only layer\");\n  }\n}\n","sourceCodeStart":22,"sourceCodeEnd":53,"githubUrl":"https://github.com/GoogleContainerTools/jib/blob/fb949e2676afbbd7dd7a1ef61e20251931325654/jib-core/src/main/java/com/google/cloud/tools/jib/image/DigestOnlyLayer.java#L22-L53","documentation":"DigestOnlyLayer represents a layer known only by its digest (no blob content). Jib throws this LayerPropertyNotFoundException from getBlob() because there is no Blob backing a digest-only layer — only the digest is stored. Callers must not request content they never supplied.","triggerScenarios":"Calling Layer.getBlob() on a layer obtained from an Image that was built with digests only (e.g. via JsonToImageTranslator.toImage or an Image built from a manifest), rather than a cached/compressed layer that carries blob data.","commonSituations":"Reading layers back from a parsed registry manifest and assuming each Layer exposes content; serializing/copying an image and attempting to re-upload layer blobs from the in-memory image; unit tests probing Layer API uniformly.","solutions":["Do not call getBlob() on digest-only layers; check the concrete Layer type first and use getBlobDescriptor().getDigest() instead","Use the layer cache (CachedLayer) or a Layer built from an actual Blob when blob content is needed","Catch LayerPropertyNotFoundException around getBlob() when iterating heterogeneous layers"],"exampleFix":"// before\nBlob blob = layer.getBlob();\n// after\nBlobDescriptor desc = layer.getBlobDescriptor();\n// use desc.getDigest() for digest-only layers; only call getBlob() on cached layers","handlingStrategy":"type-guard","validationCode":"// Java\nboolean hasBlob = !(layer instanceof DigestOnlyLayer) && !(layer instanceof ReferenceLayer);","typeGuard":"boolean hasBlob(Layer l) { return l instanceof CachedLayer || l instanceof CountingDigestOutputWriter-bearing classes; }","tryCatchPattern":"try { Blob b = layer.getBlob(); } catch (LayerPropertyNotFoundException e) { /* fall back to getBlobDescriptor().getDigest() */ }","preventionTips":["Know the concrete Layer type before calling property accessors","Use getBlobDescriptor() for digest/size on manifest-derived layers","Fetch blobs via the registry client, not the in-memory Image"],"tags":["jib","docker-image","layer","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"fb949e2676afbbd7dd7a1ef61e20251931325654","analyzedAt":"2026-09-06T14:04:09.491Z","contentChangedAt":"2026-09-06T14:04:09.491Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}