{"record":{"id":"96ec5ef4d63823b9","repo":"spring-projects/spring-ai","slug":"ioexception-wrapped-runtimeexception-96ec5e","errorCode":null,"errorMessage":"IOException (wrapped RuntimeException)","messagePattern":"IOException \\(wrapped RuntimeException\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-commons/src/main/java/org/springframework/ai/util/ResourceUtils.java","lineNumber":49,"sourceCode":"\t/**\n\t * Retrieves the content of a resource as a UTF-8 encoded string.\n\t *\n\t * This method uses Spring's DefaultResourceLoader to load the resource from the given\n\t * URI and then reads its content as a string using UTF-8 encoding. If an IOException\n\t * occurs during reading, it is wrapped in a RuntimeException.\n\t * @param uri The URI of the resource to be read. This can be any URI supported by\n\t * Spring's ResourceLoader, such as \"classpath:\", \"file:\", or \"http:\".\n\t * @return The content of the resource as a string.\n\t * @throws RuntimeException If an error occurs while reading the resource. This\n\t * exception wraps the original IOException.\n\t */\n\tpublic static String getText(String uri) {\n\t\tvar resource = new DefaultResourceLoader().getResource(uri);\n\t\ttry {\n\t\t\treturn resource.getContentAsString(StandardCharsets.UTF_8);\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n}\n","sourceCodeStart":31,"sourceCodeEnd":54,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-commons/src/main/java/org/springframework/ai/util/ResourceUtils.java#L31-L54","documentation":"ResourceUtils.getText loads a Spring Resource from a URI and reads it fully as UTF-8 text; any IOException (missing resource, unreadable file, bad URL) is rethrown as an unchecked RuntimeException wrapping the cause. There is no dedicated exception type, so callers must unwrap the cause to learn what failed.","triggerScenarios":"Calling ResourceUtils.getText(\"classpath:prompt.txt\") with a resource that does not exist, a wrong URL, an unreadable file path, or a network resource that is unavailable.","commonSituations":"Typo'd classpath resource name; file left out of the packaged jar (not in src/main/resources); loading prompts from a remote URL behind auth; running from a different working directory with relative file paths.","solutions":["Unwrap e.getCause() (IOException) to see whether it's FileNotFoundException vs connection failure","Verify the resource exists: new DefaultResourceLoader().getResource(uri).exists() before getText","For classpath resources confirm the file is under src/main/resources and packaged in the jar","Use file:/ or classpath:/ prefixes explicitly instead of relying on relative paths"],"exampleFix":"// before\nString prompt = ResourceUtils.getText(\"classpath:prompts/sys.txt\");\n// after\nResource r = new DefaultResourceLoader().getResource(\"classpath:prompts/sys.txt\");\nAssert.isTrue(r.exists(), \"Missing prompt resource: prompts/sys.txt\");\nString prompt = ResourceUtils.getText(\"classpath:prompts/sys.txt\");","handlingStrategy":"validation","validationCode":"Resource r = new DefaultResourceLoader().getResource(uri);\nif (!r.exists()) throw new IllegalStateException(\"Resource not found: \" + uri);","typeGuard":null,"tryCatchPattern":"try {\n    String text = ResourceUtils.getText(uri);\n} catch (RuntimeException e) {\n    throw new IllegalStateException(\"Cannot load resource \" + uri + \": \" + e.getCause().getMessage(), e.getCause());\n}","preventionTips":["Check resource.exists() before reading","Use explicit classpath:/file:/ prefixes","Ensure prompt files are under src/main/resources and packaged","Cache resources at startup to fail fast"],"tags":["io","resource","classpath","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-14T05:17:10.506Z"}