{"record":{"id":"81a625a708068db6","repo":"elastic/elasticsearch","slug":"failed-to-create-geoip-tmp-directory-for-project","errorCode":null,"errorMessage":"Failed to create geoip tmp directory for project [{}]","messagePattern":"Failed to create geoip tmp directory for project \\[(.+?)\\]","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"error","filePath":"modules/ip-location/src/main/java/org/elasticsearch/ingest/geoip/DatabaseNodeService.java","lineNumber":982,"sourceCode":"     * form. Names without an install-token infix (including non-mmdb side files such as\n     * {@code <dbName>_LICENSE.txt} and {@code .tmp} / {@code .tmp.retrieved} files) pass through unchanged,\n     * so this is safe to apply to every entry in the per-project tmp directory listing.\n     * <p>\n     * Package-private so internal-cluster tests can identify per-loader files by checking whether\n     * {@code stripInstallTokenInfix(name).equals(name)} is false.\n     */\n    static String stripInstallTokenInfix(String name) {\n        return INSTALL_TOKEN_INFIX.matcher(name).replaceFirst(\".mmdb\");\n    }\n\n    private Path getDatabaseTmpDirectory(ProjectId projectId) {\n        Path path = projectResolver.supportsMultipleProjects() ? geoipTmpDirectory.resolve(projectId.toString()) : geoipTmpDirectory;\n        try {\n            if (Files.exists(path) == false) {\n                Files.createDirectories(path);\n            }\n        } catch (IOException e) {\n            throw new UncheckedIOException(\"Failed to create geoip tmp directory for project [\" + projectId + \"]\", e);\n        }\n        return path;\n    }\n}\n","sourceCodeStart":964,"sourceCodeEnd":987,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/ip-location/src/main/java/org/elasticsearch/ingest/geoip/DatabaseNodeService.java#L964-L987","documentation":"Thrown by DatabaseNodeService.getDatabaseTmpDirectory when Files.createDirectories fails for the per-project geoip temp directory (geoipTmpDirectory, optionally suffixed by the project id). The IOException is wrapped in an UncheckedIOException, so it surfaces during database load/unpack on the ingest node and prevents that node from serving geoip lookups.","triggerScenarios":"Any code path that needs a temp dir to stage a downloaded mmdb (e.g. loading/unpacking a database for a project) calls getDatabaseTmpDirectory(projectId); if the path is not creatable, the UncheckedIOException fires.","commonSituations":"ES process lacks write permission on the configured geoip tmp dir; the dir was removed or its parent remounted read-only; disk full or inode exhaustion; SELinux/AppArmor denying creation; a stale file exists where a directory is expected.","solutions":["Check the path in the error: ensure its parent exists and is writable by the Elasticsearch user.","Free disk space and inodes on the volume holding the tmp dir.","If the path collides with a file, remove the file or reconfigure the geoip tmp directory setting to a clean location.","Restart the node after fixing permissions so getDatabaseTmpDirectory can recreate it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"void ensureTmpDir(Path p) throws IOException {\n    Files.createDirectories(p);\n    if (!Files.isWritable(p)) throw new IOException(\"not writable: \" + p);\n}","typeGuard":null,"tryCatchPattern":"try {\n    service.loadDatabase(...);\n} catch (UncheckedIOException e) {\n    if (e.getMessage().startsWith(\"Failed to create geoip tmp directory\")) {\n        // fix permissions/ownership of the tmp dir, free disk, then restart the node\n    } else throw e;\n}","preventionTips":["Pre-create and chown the geoip tmp directory for the Elasticsearch user during provisioning.","Monitor free disk and inodes on the volume holding the tmp dir.","Pin the geoip tmp directory setting to a dedicated writable location.","Avoid colocating the tmp dir with files that could collide."],"tags":["geoip","filesystem","permissions","disk","unpack"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}