{"record":{"id":"3d58b62473f6661a","repo":"theonedev/onedev","slug":"invalid-blob-size-s","errorCode":null,"errorMessage":"Invalid blob size: %s","messagePattern":"Invalid blob size: (.+?)","errorType":"validation","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/service/impl/DefaultPackBlobService.java","lineNumber":453,"sourceCode":"\t\t\t\tdao.persist(packBlob);\n\t\t\t\treturn new Pair<>(packBlob.getId(), true);\n\t\t\t} else if (checkPackBlobFile(projectId, sha256Hash, blobSize)) {\n\t\t\t\treturn new Pair<>(packBlob.getId(), false);\n\t\t\t} else {\n\t\t\t\treturn new Pair<>(packBlob.getId(), true);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic byte[] readBlob(Long projectId, String sha256Hash) {\n\t\tvar packBlob = findBySha256Hash(projectId, sha256Hash);\n\t\tif (packBlob != null) {\n\t\t\tvar baos = new ByteArrayOutputStream();\n\t\t\tdownloadBlob(projectId, sha256Hash, baos);\n\t\t\tvar bytes = baos.toByteArray();\n\t\t\tif (bytes.length != packBlob.getSize())\n\t\t\t\tthrow new ExplicitException(\"Invalid blob size: \" + sha256Hash);\n\t\t\treturn bytes;\n\t\t} else {\n\t\t\tthrow new ExplicitException(\"Blob not found: \" + sha256Hash);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void downloadBlob(Long projectId, String sha256Hash, OutputStream os) {\n\t\tvar activeServer = projectService.getActiveServer(projectId, true);\n\t\tif (activeServer.equals(clusterService.getLocalServerAddress())) {\n\t\t\tread(getFileLockName(projectId, sha256Hash), () -> {\n\t\t\t\ttry (var is = new FileInputStream(getPackBlobFile(projectId, sha256Hash))) {\n\t\t\t\t\tcopy(is, os, BUFFER_SIZE);\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t});\n\t\t} else {\n\t\t\tClient client = ClientBuilder.newClient();","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/service/impl/DefaultPackBlobService.java#L435-L471","documentation":"DefaultPackBlobService.readBlob downloads the blob for a sha256 hash and validates that the number of bytes read matches the size recorded in the packBlob metadata row. A mismatch means stored metadata and actual stored/transferred content disagree, so the library throws ExplicitException to prevent returning corrupt data.","triggerScenarios":"Calling PackBlobService.readBlob(projectId, sha256Hash) when the blob data on disk/object store is truncated, partially uploaded, or corrupted relative to the size recorded when the pack blob was published.","commonSituations":"Interrupted blob upload leaving a partial file; storage backend (NFS/S3) truncation or silent corruption; backup/restore mismatch between metadata DB and blob storage; concurrent modification of blob files.","solutions":["Re-publish / re-upload the affected package blob so metadata and data are rewritten","Delete the corrupt pack blob record and blob data, then republish the package","Check storage health (disk space, S3 integrity) and server logs around the upload time","Restore blob storage from a backup consistent with the database"],"exampleFix":"// before: blindly reading\nbyte[] data = packBlobService.readBlob(projectId, sha256Hash);\n// after: fall back to re-download with size check\ntry {\n    byte[] data = packBlobService.readBlob(projectId, sha256Hash);\n} catch (ExplicitException e) {\n    if (e.getMessage().startsWith(\"Invalid blob size\")) {\n        // republish blob or fetch from upstream registry\n    }\n    throw e;\n}","handlingStrategy":"retry","validationCode":"var blob = packBlobService.findBySha256Hash(projectId, sha256Hash);\nif (blob == null) throw new ExplicitException(\"Blob not published: \" + sha256Hash);","typeGuard":null,"tryCatchPattern":"try {\n    return packBlobService.readBlob(projectId, sha256Hash);\n} catch (ExplicitException e) {\n    if (e.getMessage().startsWith(\"Invalid blob size\")) {\n        // mark blob corrupt and re-upload before retrying\n    }\n    throw e;\n}","preventionTips":["Monitor storage integrity (fsck/object-store checks) on blob volumes","Avoid interrupting blob uploads; use atomic temp-file + rename writes","Keep DB and blob storage backups taken together","Alert on disk-full / truncated upload conditions"],"tags":["integrity","storage","checksum","package-registry"],"backgroundTag":"checksum-mismatch","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}