{"record":{"id":"0b63287031445c29","repo":"elastic/elasticsearch","slug":"malformed-lucene-snapshot-version-luceneversion","errorCode":null,"errorMessage":"Malformed lucene snapshot version: ${luceneVersion}","messagePattern":"Malformed lucene snapshot version: (.+?)","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RepositoriesSetupPlugin.java","lineNumber":50,"sourceCode":"    /**\n     * Adds repositories used by ES projects and dependencies\n     */\n    public static void configureRepositories(Project project) {\n        RepositoryHandler repos = project.getRepositories();\n        if (System.getProperty(\"repos.mavenLocal\") != null) {\n            // with -Drepos.mavenLocal=true we can force checking the local .m2 repo which is\n            // useful for development ie. bwc tests where we install stuff in the local repository\n            // such that we don't have to pass hardcoded files to gradle\n            repos.mavenLocal();\n        }\n        repos.mavenCentral();\n\n        String luceneVersion = VersionProperties.getLucene();\n        if (luceneVersion.contains(\"-snapshot\")) {\n            // extract the revision number from the version with a regex matcher\n            Matcher matcher = LUCENE_SNAPSHOT_REGEX.matcher(luceneVersion);\n            if (matcher.find() == false) {\n                throw new GradleException(\"Malformed lucene snapshot version: \" + luceneVersion);\n            }\n            String revision = matcher.group(1);\n            MavenArtifactRepository luceneRepo = repos.maven(repo -> {\n                repo.setName(\"lucene-snapshots\");\n                repo.setUrl(\"https://s3.amazonaws.com/download.elasticsearch.org/lucenesnapshots/\" + revision);\n            });\n            repos.exclusiveContent(exclusiveRepo -> {\n                exclusiveRepo.filter(\n                    descriptor -> descriptor.includeVersionByRegex(\"org\\\\.apache\\\\.lucene\", \".*\", \".*-snapshot-\" + revision)\n                );\n                exclusiveRepo.forRepositories(luceneRepo);\n            });\n        }\n\n        String cuvsVersion = VersionProperties.getVersions().get(\"cuvs_java\");\n        if (cuvsVersion.contains(\"-SNAPSHOT\")) {\n            MavenArtifactRepository cuvsRepo = repos.maven(repo -> {\n                repo.setName(\"cuvs-snapshots\");","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/RepositoriesSetupPlugin.java#L32-L68","documentation":"Thrown by RepositoriesSetupPlugin.configureRepositories when the Lucene version (from VersionProperties.getLucene()) contains '-snapshot' but does not match LUCENE_SNAPSHOT_REGEX '\\\\w+-snapshot-([a-z0-9]+)'. The regex extracts the alphanumeric revision so the plugin can build the S3 snapshot repository URL and the exclusive-content version filter; a snapshot version without a parseable revision suffix cannot be wired to a repository.","triggerScenarios":"luceneVersion.contains(\"-snapshot\") is true, but LUCENE_SNAPSHOT_REGEX.matcher(luceneVersion).find() is false. The regex expects the form '<something>-snapshot-<revision>' where revision is lowercase letters/digits (e.g. '9.10.0-snapshot-1a2b3c').","commonSituations":"VersionProperties lucene version malformed (missing the revision tail after '-snapshot'); a version like '9.10.0-SNAPSHOT' (Maven-style uppercase, no revision — does not contain lowercase '-snapshot'); uppercase letters or symbols in the revision that violate [a-z0-9]+; manually editing version.properties with a non-canonical snapshot string.","solutions":["Set the lucene version in VersionProperties to the canonical snapshot form '<base>-snapshot-<revision>', e.g. '9.12.0-snapshot-9abc123'.","Use only lowercase [a-z0-9] in the revision portion (the regex is case-sensitive).","If you intentionally want a non-snapshot Lucene, remove the '-snapshot' segment entirely so the contains() guard is false and no regex parse is attempted.","Regenerate version properties through the build's versioning tooling rather than hand-editing."],"exampleFix":"// before (version.properties): lucene = 9.12.0-SNAPSHOT\n// after:                  lucene = 9.12.0-snapshot-9abc123","handlingStrategy":"validation","validationCode":"import java.util.regex.Pattern;\nprivate static final Pattern LUCENE_SNAPSHOT = Pattern.compile(\"\\\\w+-snapshot-([a-z0-9]+)\");\nvoid checkLuceneVersion(String v) {\n    if (v.contains(\"-snapshot\")) {\n        if (!LUCENE_SNAPSHOT.matcher(v).find())\n            throw new IllegalArgumentException(\"bad lucene snapshot version: \" + v);\n    }\n}\n// canonical: \"9.12.0-snapshot-9abc123\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use the canonical '<base>-snapshot-<lowercase-revision>' form in version.properties.","Keep the revision lowercase [a-z0-9]; the regex is case-sensitive.","Generate version properties through the build's versioning tooling, not by hand."],"tags":["gradle","lucene","versioning","repositories","snapshot"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}