{"record":{"id":"be4b3411a129f23e","repo":"apache/pulsar","slug":"log-folder-creation-error","errorCode":null,"errorMessage":"Log folder creation error","messagePattern":"Log folder creation error","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/process/ProcessRuntime.java","lineNumber":169,"sourceCode":"\n    /**\n     * The core logic that initialize the process container and executes the function.\n     */\n    @Override\n    public void start() {\n        java.lang.Runtime.getRuntime().addShutdownHook(new Thread(() -> process.destroy()));\n\n        // Note: we create the expected log folder before the function process logger attempts to create it\n        // This is because if multiple instances are launched they can encounter a race condition creation of the dir.\n\n        log.info().attr(\"logDir\", funcLogDir).log(\"Creating function log directory\");\n\n        try {\n            Files.createDirectories(Paths.get(funcLogDir));\n        } catch (IOException e) {\n            log.info().attr(\"logDir\", funcLogDir).exception(e)\n                    .log(\"Exception when creating log folder\");\n            throw new RuntimeException(\"Log folder creation error\");\n        }\n\n        log.info().attr(\"logDir\", funcLogDir).log(\"Created or found function log directory\");\n\n        startProcess();\n        if (channel == null && stub == null) {\n            channel = ManagedChannelBuilder.forAddress(\"127.0.0.1\", instancePort)\n                    .usePlaintext()\n                    .build();\n            stub = InstanceControlGrpc.newStub(channel);\n\n            timer = InstanceCache.getInstanceCache().getScheduledExecutorService()\n                    .scheduleAtFixedRate(catchingAndLoggingThrowables(() -> {\n                        CompletableFuture<HealthCheckResult> result = healthCheck();\n                        try {\n                            result.get();\n                        } catch (Exception e) {\n                            log.error().attr(\"name\", instanceConfig.getFunctionDetails().getName())","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/runtime/src/main/java/org/apache/pulsar/functions/runtime/process/ProcessRuntime.java#L151-L187","documentation":"ProcessRuntime.start() creates the function's log directory (funcLogDir) via Files.createDirectories before spawning the function process. If directory creation fails with an IOException (permissions, path is a file, filesystem full), it logs the cause and rethrows a plain RuntimeException('Log folder creation error'), which aborts starting the function instance.","triggerScenarios":"Starting a ProcessRuntime (local runner / process container) when the configured log directory cannot be created: parent dir not writable, path exists as a regular file, disk full, read-only mount, or invalid path characters/permissions inside the function worker container.","commonSituations":"pulsar.functions.process.container.log.dir pointing to a non-writable path in the container; running the worker as a non-root user against a root-owned log dir; Kubernetes volume mounted read-only; leftover file occupying the log directory path after a crash.","solutions":["Check the preceding 'Exception when creating log folder' log line for the underlying IOException cause and fix it (permissions, disk space, path).","Ensure the log directory path (and parents) is writable by the user running the function worker.","Verify pulsar.functions.process.container.log.dir points to a directory, not an existing file, and is on a writable volume.","Restart the worker after fixing the environment; the exception is thrown at start time only."],"exampleFix":"# before\n$ ls -ld /pulsar/logs  # root-owned, worker runs as pulsar\n# after\n$ sudo chown -R pulsar:pulsar /pulsar/logs && sudo chmod u+rwx /pulsar/logs","handlingStrategy":"validation","validationCode":"Path logDir = Paths.get(funcLogDir);\nif (Files.exists(logDir) && !Files.isDirectory(logDir)) {\n    throw new IllegalStateException(funcLogDir + \" exists but is not a directory\");\n}\nif (!Files.isWritable(logDir.getParent() != null ? logDir.getParent() : logDir)) {\n    throw new IllegalStateException(\"log dir parent not writable: \" + logDir.getParent());\n}","typeGuard":null,"tryCatchPattern":"try {\n    runtime.start();\n} catch (RuntimeException e) {\n    if (\"Log folder creation error\".equals(e.getMessage())) {\n        // inspect the preceding 'Exception when creating log folder' log line, fix perms/disk, retry\n    }\n    throw e;\n}","preventionTips":["Pre-create the container log directory with correct ownership in the image/entrypoint.","Mount the log volume read-write, never read-only.","Monitor disk space on the log volume.","Run the worker as a user that owns or can write the log path."],"tags":["pulsar-functions","filesystem","io","runtime"],"backgroundTag":"log-directory-not-writable","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}