{"record":{"id":"747d8c5d136342ab","repo":"oracle/graal","slug":"cannot-use-the-specified-log-file","errorCode":null,"errorMessage":"Cannot use the specified log.file","messagePattern":"Cannot use the specified log\\.file","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccessBuilder.java","lineNumber":207,"sourceCode":"        String group = key;\n        if (index >= 0) {\n            group = group.substring(0, index);\n        }\n        if (\"log\".equals(group)) {\n            if (key.endsWith(\".level\")) {\n                try {\n                    Level.parse(value);\n                    builder.option(key, value);\n                } catch (IllegalArgumentException e) {\n                    throw new IllegalArgumentException(String.format(\"Invalid log level %s specified. %s'\", vmOption, e.getMessage()));\n                }\n                return;\n            } else if (\"log.file\".equals(key)) {\n                OutputStream out;\n                try {\n                    out = new BufferedOutputStream(Files.newOutputStream(Paths.get(value), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND));\n                } catch (IOException e) {\n                    throw new IllegalArgumentException(\"Cannot use the specified log.file\", e);\n                }\n                builder.logHandler(out);\n                return;\n            }\n        }\n        OptionDescriptor descriptor = findOptionDescriptor(group, key);\n        if (descriptor == null) {\n            key = JAVA_LANGUAGE_ID + \".\" + key;\n            descriptor = findOptionDescriptor(JAVA_LANGUAGE_ID, key);\n            if (descriptor == null) {\n                throw new IllegalArgumentException(\"Unrecognized VM option: '\" + vmOption);\n            }\n        }\n        try {\n            descriptor.getKey().getType().convert(value);\n        } catch (IllegalArgumentException e) {\n            throw new IllegalArgumentException(String.format(\"Invalid VM option %s specified. %s\", vmOption, e.getMessage()));\n        }","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso-compiler-stub/src/com.oracle.truffle.espresso.vmaccess/src/com/oracle/truffle/espresso/vmaccess/EspressoExternalVMAccessBuilder.java#L189-L225","documentation":"Thrown when the 'log.file' VM option is processed: Espresso tries to open the given path with Files.newOutputStream(WRITE, CREATE, APPEND) and the IOException is wrapped in IllegalArgumentException('Cannot use the specified log.file'). The stream becomes the engine's log handler, so it must be openable at build time.","triggerScenarios":"Setting a 'java.log.file=<path>' option where the path cannot be opened for append: nonexistent parent directory, no write permission, path is a directory, read-only filesystem, or invalid path syntax on the platform.","commonSituations":"Relative log paths resolved against an unexpected working directory (service/daemon cwd); container or read-only mount without a writable /var/log; SELinux/AppArmor denying writes; path with spaces or special characters not properly escaped in the option string.","solutions":["Pre-create the parent directory and verify writability of the exact resolved path before building the VMAccess","Use an absolute path for log.file so it does not depend on the process working directory","Check filesystem permissions/mount flags (read-only container volumes) and pick a writable location such as the temp dir"],"exampleFix":"// before\nbuilder.option(\"java.log.file\", \"logs/espresso.log\"); // 'logs/' may not exist\n\n// after\nPath logPath = Path.of(\"/var/myapp/log/espresso.log\").toAbsolutePath();\nFiles.createDirectories(logPath.getParent());\nbuilder.option(\"java.log.file\", logPath.toString());","handlingStrategy":"try-catch","validationCode":"Path p = Path.of(logFile).toAbsolutePath();\nFiles.createDirectories(p.getParent());\nif (!Files.isWritable(p.getParent())) throw new IOException(\"log dir not writable: \" + p.getParent());","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) when message contains 'log.file': report the resolved absolute path and permissions, suggest a writable directory","preventionTips":["Use absolute log paths so behavior does not depend on process cwd","Pre-create the log directory at deployment time and verify writability in startup checks","In containers, mount a writable volume for logs"],"tags":["espresso","configuration","logging","filesystem","io"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}