{"record":{"id":"6bbfcea02e05d496","repo":"elastic/elasticsearch","slug":"cannot-use-a-commit-sha-branchref-as-branch","errorCode":null,"errorMessage":"Cannot use a commit SHA ({branchRef}) as --branch when fetching external changelog sources: git fetch on the remote repository requires a branch or tag name. Local Elasticsearch changelog YAML can still be checked out from a SHA; pass a named branch for --branch (and use --bc-ref for the build candidate when applicable).","messagePattern":"Cannot use a commit SHA \\((.+?)\\) as --branch when fetching external changelog sources: git fetch on the remote repository requires a branch or tag name\\. Local Elasticsearch changelog YAML can still be checked out from a SHA; pass a named branch for --branch \\(and use --bc-ref for the build candidate when applicable\\)\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BundleChangelogsTask.java","lineNumber":472,"sourceCode":"    /**\n     * Normalizes a branch reference for use with external repos. Strips known\n     * remote prefixes ({@code upstream/}, {@code origin/}) which are ES-repo-specific,\n     * and when {@code esUpstreamRemote} is set, strips {@code <remote>/} for the\n     * Elasticsearch remote name returned by {@link GitWrapper#getUpstream()} (e.g.\n     * {@code elastic/main} → {@code main}) so {@code git fetch} targets a branch that\n     * exists on the external repository.\n     * <p>\n     * Raw commit SHAs are rejected since they are meaningless for external repositories.\n     * Other refs (including branch names with slashes like {@code feature/foo}) are passed\n     * through except for the prefixes above.\n     */\n    static String normalizeBranchForExternalFetch(String branchRef) {\n        return normalizeBranchForExternalFetch(branchRef, null);\n    }\n\n    static String normalizeBranchForExternalFetch(String branchRef, @Nullable String esUpstreamRemote) {\n        if (isShaRef(branchRef)) {\n            throw new IllegalArgumentException(\n                \"Cannot use a commit SHA (\"\n                    + branchRef\n                    + \") as --branch when fetching external changelog sources: \"\n                    + \"git fetch on the remote repository requires a branch or tag name. \"\n                    + \"Local Elasticsearch changelog YAML can still be checked out from a SHA; \"\n                    + \"pass a named branch for --branch (and use --bc-ref for the build candidate when applicable).\"\n            );\n        }\n        for (String prefix : KNOWN_REMOTE_PREFIXES) {\n            if (branchRef.startsWith(prefix)) {\n                return branchRef.substring(prefix.length());\n            }\n        }\n        if (esUpstreamRemote != null && esUpstreamRemote.isBlank() == false) {\n            String remotePrefix = esUpstreamRemote + \"/\";\n            if (branchRef.startsWith(remotePrefix)) {\n                return branchRef.substring(remotePrefix.length());\n            }","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BundleChangelogsTask.java#L454-L490","documentation":"Thrown by BundleChangelogsTask.normalizeBranchForExternalFetch when the --branch value looks like a raw commit SHA (matched by isShaRef). External repositories cannot be fetched by SHA via `git fetch <url> <sha>` (git requires a named ref), so the task rejects SHAs early and instructs the user to pass a named branch for --branch and use --bc-ref for a build-candidate SHA.","triggerScenarios":"The user supplies a 40-char (or short) hex SHA as --branch. Because external changelog sources are fetched from their own remotes where a commit SHA is not a fetchable refspec, normalizeBranchForExternalFetch refuses it and throws IllegalArgumentException with remediation guidance.","commonSituations":"Copy-pasting a build-candidate SHA into --branch instead of --bc-ref; assuming a SHA works universally for local and external checkouts; release tooling that previously accepted SHAs before external sources were added.","solutions":["Pass a real branch name to --branch (e.g. --branch 8.x) and pass the build-candidate SHA via --bc-ref instead.","If you only have a SHA and want local Elasticsearch changelog YAML, that path still supports SHAs via --bc-ref; external sources require the named branch.","Update release scripts that pass SHAs as --branch to split them into --branch <name> and --bc-ref <sha>."],"exampleFix":"// before\n./gradlew bundleChangelogs --branch abc123def456...\n// after\n./gradlew bundleChangelogs --branch 8.x --bc-ref abc123def456...","handlingStrategy":"validation","validationCode":"static boolean isShaRef(String ref) { return ref.matches(\"^[0-9a-f]{4,40}$\"); }\nif (isShaRef(branchArg)) {\n    throw new IllegalArgumentException(\"Pass a named branch via --branch; use --bc-ref for SHAs.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass a named branch to --branch and a SHA to --bc-ref.","Validate the --branch shape in release scripts before invoking Gradle.","Keep the distinction documented in the release runbook."],"tags":["build","gradle","release","changelog","git","cli-args"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}