{"record":{"id":"02b07bce90cd075b","repo":"jeecgboot/JeecgBoot","slug":"error-02b07b","errorCode":null,"errorMessage":"生成验证码图片失败","messagePattern":"生成验证码图片失败","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/util/RandImageUtil.java","lineNumber":74,"sourceCode":"    private static final int CHAR_X_OFFSET = 8;\n\n    /**\n     * 直接通过response输出验证码图片\n     * \n     * @param response HTTP响应对象\n     * @param verifyCode 验证码字符串\n     * @throws IOException 输出异常\n     */\n    public static void generate(HttpServletResponse response, String verifyCode) throws IOException {\n        if (response == null || verifyCode == null || verifyCode.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"参数不能为空\");\n        }\n        \n        try {\n            BufferedImage image = createVerifyCodeImage(verifyCode);\n            ImageIO.write(image, IMG_FORMAT, response.getOutputStream());\n        } catch (Exception e) {\n            throw new IOException(\"生成验证码图片失败\", e);\n        }\n    }\n\n    /**\n     * 生成验证码的base64字符串\n     * \n     * @param verifyCode 验证码字符串\n     * @return base64编码的图片字符串\n     * @throws IOException 生成异常\n     */\n    public static String generate(String verifyCode) throws IOException {\n        if (verifyCode == null || verifyCode.trim().isEmpty()) {\n            throw new IllegalArgumentException(\"验证码不能为空\");\n        }\n        \n        try {\n            BufferedImage image = createVerifyCodeImage(verifyCode);\n            ","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/util/RandImageUtil.java#L56-L92","documentation":"Thrown by RandImageUtil.generate(HttpServletResponse, String) when ImageIO.write fails to write the captcha BufferedImage to the servlet response output stream. The method wraps any Exception (I/O error, image encoding failure, closed/disposed response stream) in an IOException with this message. Note that createVerifyCodeImage itself has an internal fallback (createErrorImage), so this outer exception typically originates from ImageIO.write or response.getOutputStream() rather than from the drawing logic.","triggerScenarios":"The HttpServletResponse output stream is already closed or committed before generate() is called. A headless server without proper AWT font configuration causes JPEG encoding to fail (though the static block sets java.awt.headless=true). The response content type was not set to image/jpeg before writing. Memory pressure causes BufferedImage allocation to fail. The servlet container has already flushed the response buffer.","commonSituations":"Running in a minimal Docker container without font packages installed (e.g., vanilla alpine without fontconfig/dejavu fonts). Calling response.getWriter() before response.getOutputStream() (illegal state). Interceptor/filter that commits the response before the captcha controller runs. Heavy load causing transient OOM during image allocation.","solutions":["Ensure the Docker/base image has font packages: for Debian-based images install 'fonts-dejavu-core fontconfig'; for Alpine install 'fontconfig ttf-dejavu'.","Verify the controller sets response.setContentType(\"image/jpeg\") and does not call response.getWriter() anywhere before generate().","Check that no filter or interceptor commits/flushes the response before the captcha endpoint executes."],"exampleFix":"// before: no content-type header, possible writer conflict\n@RestController\npublic class CaptchaController {\n    @GetMapping(\"/captcha\")\n    public void captcha(HttpServletResponse response, String verifyCode) throws IOException {\n        RandImageUtil.generate(response, verifyCode);\n    }\n}\n\n// after: set content-type and reset buffer before writing\n@GetMapping(\"/captcha\")\npublic void captcha(HttpServletResponse response, String verifyCode) throws IOException {\n    response.setContentType(\"image/jpeg\");\n    response.setHeader(\"Cache-Control\", \"no-store, no-cache\");\n    response.resetBuffer();\n    RandImageUtil.generate(response, verifyCode);\n}","handlingStrategy":"try-catch","validationCode":"// Ensure response is ready for binary output before calling generate\npublic void safeGenerateCaptcha(HttpServletResponse response, String verifyCode) {\n    if (response == null || verifyCode == null || verifyCode.trim().isEmpty()) {\n        throw new IllegalArgumentException(\"参数不能为空\");\n    }\n    response.setContentType(\"image/jpeg\");\n    response.setHeader(\"Cache-Control\", \"no-store, no-cache\");\n    response.setHeader(\"Pragma\", \"no-cache\");\n    try {\n        RandImageUtil.generate(response, verifyCode);\n    } catch (IOException e) {\n        log.error(\"Failed to generate captcha image\", e);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    response.setContentType(\"image/jpeg\");\n    response.setHeader(\"Cache-Control\", \"no-store\");\n    RandImageUtil.generate(response, verifyCode);\n} catch (IOException e) {\n    log.error(\"Captcha image generation failed\", e);\n    response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);\n}","preventionTips":["Always set response.setContentType(\"image/jpeg\") before calling generate().","Never call response.getWriter() before response.getOutputStream() — this causes an IllegalStateException.","Ensure the Docker/container image has fontconfig and DejaVu fonts installed.","Set -Djava.awt.headless=true in JVM args (the utility does this in a static block, but verify for your environment).","Avoid calling response.flushBuffer() or committing the response before generate() runs."],"tags":["captcha","imageio","headless","servlet","jeecg-boot"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}