{"record":{"id":"e52351ed5d6d089d","repo":"spring-projects/spring-ai","slug":"failed-to-read-resource-e52351","errorCode":null,"errorMessage":"Failed to read resource","messagePattern":"Failed to read resource","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-model/src/main/java/org/springframework/ai/chat/messages/MessageUtils.java","lineNumber":48,"sourceCode":" * @author Thomas Vitale\n */\nfinal class MessageUtils {\n\n\tprivate MessageUtils() {\n\t}\n\n\tstatic String readResource(Resource resource) {\n\t\treturn readResource(resource, Charset.defaultCharset());\n\t}\n\n\tstatic String readResource(Resource resource, Charset charset) {\n\t\tAssert.notNull(resource, \"resource cannot be null\");\n\t\tAssert.notNull(charset, \"charset cannot be null\");\n\t\ttry (InputStream inputStream = resource.getInputStream()) {\n\t\t\treturn StreamUtils.copyToString(inputStream, charset);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new RuntimeException(\"Failed to read resource\", ex);\n\t\t}\n\t}\n\n}\n","sourceCodeStart":30,"sourceCodeEnd":53,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-model/src/main/java/org/springframework/ai/chat/messages/MessageUtils.java#L30-L53","documentation":"MessageUtils.readResource reads a Spring Resource fully into a String using the given charset; any IOException is wrapped in a RuntimeException with message 'Failed to read resource' and the original exception as cause. It is the low-level loader used by SystemMessage/UserMessage builders to read media/text resources.","triggerScenarios":"Building a SystemMessage/UserMessage from a Resource whose stream cannot be opened: missing classpath entry, wrong URL, closed filesystem, or inaccessible file.","commonSituations":"Passing new ClassPathResource(\"prompts/system.txt\") where the file is missing from the jar; loading from an external file:// path that doesn't exist at runtime; container images without the bundled resource.","solutions":["Unwrap ex.getCause() (IOException) to identify FileNotFoundException vs other IO problems","Call resource.exists() before building the message and fail fast with a clear message","Ensure the file is in src/main/resources so it lands in the classpath jar","For external files, verify the absolute path and permissions at startup"],"exampleFix":"// before\nSystemMessage msg = SystemMessage.builder().resource(new ClassPathResource(\"prompts/sys.txt\")).build();\n// after\nResource r = new ClassPathResource(\"prompts/sys.txt\");\nAssert.isTrue(r.exists(), \"prompts/sys.txt not found on classpath\");\nSystemMessage msg = SystemMessage.builder().resource(r).build();","handlingStrategy":"validation","validationCode":"Resource r = new ClassPathResource(\"prompts/sys.txt\");\nif (!r.exists()) throw new IllegalStateException(\"Missing resource: prompts/sys.txt\");","typeGuard":null,"tryCatchPattern":"try {\n    String text = MessageUtils.readResource(resource, StandardCharsets.UTF_8);\n} catch (RuntimeException e) {\n    throw new IllegalStateException(\"Cannot read \" + resource + \": \" + e.getCause().getMessage(), e.getCause());\n}","preventionTips":["Check resource.exists() before building messages","Keep prompt files in src/main/resources","Fail fast at application startup by loading required prompts once"],"tags":["io","resource","classpath","chat-messages","spring-ai"],"backgroundTag":"file-read-failed","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}