{"record":{"id":"ea2b43de8b377f60","repo":"conductor-oss/conductor","slug":"file-not-found-on-storage-backend","errorCode":null,"errorMessage":"File not found on storage backend: {}","messagePattern":"File not found on storage backend: (.+?)","errorType":"exception","errorClass":"NonTransientException","httpStatus":500,"severity":"error","filePath":"core/src/main/java/org/conductoross/conductor/core/storage/FileStorageServiceImpl.java","lineNumber":107,"sourceCode":"        long expiresAt = Instant.now().plus(properties.getSignedUrlExpiration()).toEpochMilli();\n\n        FileUploadUrlResponse response = new FileUploadUrlResponse();\n        response.setFileHandleId(FileIdToFileHandleIdConverter.toFileHandleId(fileId));\n        response.setUploadUrl(uploadUrl);\n        response.setExpiresAt(expiresAt);\n        return response;\n    }\n\n    @Override\n    public FileUploadCompleteResponse confirmUpload(String workflowId, String fileId) {\n        FileModel model = getOwnedFile(workflowId, fileId);\n        if (model.getUploadStatus() == FileUploadStatus.UPLOADED) {\n            throw new ConflictException(\"File already uploaded: \" + fileId);\n        }\n\n        StorageFileInfo info = fileStorage.getStorageFileInfo(model.getStoragePath());\n        if (info == null || !info.isExists()) {\n            throw new NonTransientException(\"File not found on storage backend: \" + fileId);\n        }\n\n        fileMetadataDAO.updateUploadComplete(\n                fileId, FileUploadStatus.UPLOADED, info.getContentHash(), info.getContentSize());\n\n        FileUploadCompleteResponse response = new FileUploadCompleteResponse();\n        response.setFileHandleId(FileIdToFileHandleIdConverter.toFileHandleId(fileId));\n        response.setUploadStatus(FileUploadStatus.UPLOADED);\n        response.setContentHash(info.getContentHash());\n        return response;\n    }\n\n    @Override\n    public FileDownloadUrlResponse getDownloadUrl(String workflowId, String fileId) {\n        FileModel model = getFamilyAccessibleFile(workflowId, fileId);\n        if (model.getUploadStatus() != FileUploadStatus.UPLOADED) {\n            throw new IllegalArgumentException(\n                    \"File not yet uploaded: \" + fileId + \", status=\" + model.getUploadStatus());","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/org/conductoross/conductor/core/storage/FileStorageServiceImpl.java#L89-L125","documentation":"Thrown by FileStorageServiceImpl.confirmUpload after getOwnedFile succeeds but fileStorage.getStorageFileInfo reports the object is absent (null or exists=false). The metadata record exists but the actual bytes were never written to the backend, so the upload cannot be confirmed. Raised as NonTransientException (not retried; HTTP 4xx).","triggerScenarios":"Calling confirmUpload without first uploading bytes to the presigned URL; the PUT to the upload URL failed silently; eventual-consistency delay where the backend has not yet registered the object; backend misconfiguration pointing at the wrong bucket/container.","commonSituations":"Client generated the file record and immediately confirmed without uploading content; presigned PUT returned an error the client ignored; clock/propagation delay on a strongly consistent backend; wrong storage credentials so bytes went elsewhere.","solutions":["Ensure the content was actually uploaded to the returned presigned URL before confirming.","Re-request the upload URL (getUploadUrl) and PUT the bytes, then confirm again.","Verify backend credentials/bucket match the configuration.","If the backend is eventually consistent, retry confirm after a short delay only if transient."],"exampleFix":"// before\nFileUploadResponse r = fileStorageService.createFile(req);\n// forgot to PUT bytes to r.getUploadUrl()\nfileStorageService.confirmUpload(wfId, r.getFileId()); // throws\n\n// after\nFileUploadResponse r = fileStorageService.createFile(req);\nhttp.put(r.getUploadUrl(), fileBytes);\nfileStorageService.confirmUpload(wfId, r.getFileId());","handlingStrategy":"validation","validationCode":"StorageFileInfo info = fileStorage.getStorageFileInfo(storagePath);\nif (info == null || !info.isExists()) { /* upload bytes before confirming */ }","typeGuard":null,"tryCatchPattern":"try {\n    fileStorageService.confirmUpload(wfId, fileId);\n} catch (NonTransientException e) {\n    // object missing on backend; re-upload then confirm\n}","preventionTips":["PUT bytes to the presigned URL before confirmUpload","Verify backend credentials/bucket config","Check the presigned PUT response status"],"tags":["file-storage","upload","backend","missing-content","conductor","java"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}