{"record":{"id":"cdcde398c503f8d5","repo":"flowable/flowable-engine","slug":"byte-array-for-resource-resourcename-is-null","errorCode":null,"errorMessage":"byte array for resource '${resourceName}' is null","messagePattern":"byte array for resource '(.+?)' is null","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/repository/AppDeploymentBuilderImpl.java","lineNumber":62,"sourceCode":"        this.deployment = appEngineConfiguration.getAppDeploymentEntityManager().create();\n        this.resourceEntityManager = appEngineConfiguration.getAppResourceEntityManager();\n    }\n\n    @Override\n    public AppDeploymentBuilder addInputStream(String resourceName, InputStream inputStream) {\n        if (inputStream == null) {\n            throw new FlowableException(\"inputStream for resource '\" + resourceName + \"' is null\");\n        }\n\n        byte[] bytes = null;\n        try {\n            bytes = IoUtil.readInputStream(inputStream, resourceName);\n        } catch (Exception e) {\n            throw new FlowableException(\"could not get byte array from resource '\" + resourceName + \"'\", e);\n        }\n\n        if (bytes == null) {\n            throw new FlowableException(\"byte array for resource '\" + resourceName + \"' is null\");\n        }\n\n        AppResourceEntity resource = resourceEntityManager.create();\n        resource.setName(resourceName);\n        resource.setBytes(bytes);\n        deployment.addResource(resource);\n        return this;\n    }\n\n    @Override\n    public AppDeploymentBuilder addClasspathResource(String resource) {\n        try (final InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(resource)) {\n            if (inputStream == null) {\n                throw new FlowableException(\"resource '\" + resource + \"' not found\");\n            }\n            \n            return addInputStream(resource, inputStream);\n            ","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-app-engine/src/main/java/org/flowable/app/engine/impl/repository/AppDeploymentBuilderImpl.java#L44-L80","documentation":"After reading, addInputStream() checks the resulting byte array and throws FlowableException('byte array for resource ... is null') if IoUtil.readInputStream somehow returned null. This is a defensive post-condition: a successful read must always yield bytes, so null indicates a pathological stream implementation.","triggerScenarios":"A custom or mock InputStream whose read() methods report data but never actually deliver bytes, or a corrupted/unusual stream implementation that makes IoUtil.readInputStream return null without throwing.","commonSituations":"Unit tests with hand-rolled or mocked streams that misbehave; exotic stream wrappers (e.g. decompressing streams) that return null results; rarely seen with normal file/classpath streams.","solutions":["Replace the custom/mocked InputStream with a standard one (ByteArrayInputStream, FileInputStream) that yields real bytes.","Verify the stream's read(byte[], int, int) implementation follows the InputStream contract.","Pre-add the resource bytes yourself via addInputStream(name, new ByteArrayInputStream(data)) to bypass the faulty source."],"exampleFix":"// before\nInputStream in = new BrokenMockStream(); // read() returns 0, produces null bytes\ndeploymentBuilder.addInputStream(name, in);\n\n// after\nbyte[] data = Files.readAllBytes(Paths.get(filePath));\ndeploymentBuilder.addInputStream(name, new ByteArrayInputStream(data));","handlingStrategy":"try-catch","validationCode":"byte[] data = IoUtil.readInputStream(inputStream, resourceName); if (data == null || data.length == 0) { throw new IllegalStateException(\"Stream produced no bytes\"); }","typeGuard":null,"tryCatchPattern":"try { deploymentBuilder.addInputStream(name, in); } catch (FlowableException e) { log.error(\"Stream for {} yielded no bytes; check stream implementation\", name); }","preventionTips":["Prefer standard stream implementations (ByteArrayInputStream, FileInputStream) over hand-rolled ones.","In tests, mock at the file/source level rather than providing fake InputStream implementations.","Sanity-check custom streams against the InputStream contract (read returns -1 at EOF, delivers real bytes)."],"tags":["flowable","deployment","stream-contract"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}