{"record":{"id":"521c837dc09783ac","repo":"kestra-io/kestra","slug":"digest-authentication-requires-both-username-and","errorCode":null,"errorMessage":"Digest authentication requires both `username` and `password`.","messagePattern":"Digest authentication requires both `username` and `password`\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/http/client/HttpClient.java","lineNumber":478,"sourceCode":"            .name(eventName)\n            .comment(comment)\n            .retry(retry)\n            .build();\n\n        if (eventConsumer != null) {\n            eventConsumer.accept(event);\n        }\n    }\n\n    private HttpClientContext clientContext(HttpRequest request) throws IllegalVariableEvaluationException {\n        HttpClientContext httpClientContext = ContextBuilder.create().build();\n\n        if (this.configuration.getAuth() instanceof DigestAuthConfiguration digestAuthConfiguration) {\n            String username = runContext.render(digestAuthConfiguration.getUsername()).as(String.class).orElse(null);\n            String password = runContext.render(digestAuthConfiguration.getPassword()).as(String.class).orElse(null);\n\n            if (StringUtils.isEmpty(username) || password == null) {\n                throw new IllegalArgumentException(\"Digest authentication requires both `username` and `password`.\");\n            }\n\n            URI uri = request.getUri();\n            if (uri == null || uri.getHost() == null) {\n                throw new IllegalArgumentException(\"Digest authentication requires an absolute URI with a host.\");\n            }\n\n            int port = uri.getPort() != -1 ? uri.getPort() : (\"https\".equalsIgnoreCase(uri.getScheme()) ? 443 : 80);\n            AuthScope digestScope = new AuthScope(uri.getHost(), port);\n            UsernamePasswordCredentials digestCredentials = new UsernamePasswordCredentials(username, password.toCharArray());\n\n            httpClientContext.setCredentialsProvider((authScope, context) ->\n            {\n                if (digestScope.match(authScope) >= 0) {\n                    return digestCredentials;\n                }\n                return this.defaultCredentialsProvider.getCredentials(authScope, context);\n            });","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/http/client/HttpClient.java#L460-L496","documentation":"Thrown by the Kestra HTTP client when digest authentication is configured but credentials are incomplete. clientContext renders username/password via the run context; if username is empty (after render) or password is null, it throws IllegalArgumentException. Blank-but-non-null password is allowed; only a missing password value triggers it.","triggerScenarios":"Task uses HttpClient with auth.type=digest; runContext.render(digestAuthConfiguration.getUsername()).as(String) yields empty OR runContext.render(password).as(String) yields null; the StringUtils.isEmpty(username) || password == null guard throws.","commonSituations":"Username/password secret not resolved (missing secret), the rendered expression evaluates to empty, a typo in the property name, or the password field omitted from the task config.","solutions":["Provide both username and password in the digest auth configuration.","If using secret expressions ({{ secret('USER') }}), confirm the secret exists and resolves to a non-empty value.","Double-check the property names match DigestAuthConfiguration (username, password).","Test the rendered value with a debug log or a no-op task that prints the resolved length."],"exampleFix":"# before\n- id: http\n  type: io.kestra.plugin.core.http.Request\n  auth:\n    type: digest\n    username: \"{{ secret('API_USER') }}\"\n    # password missing\n# after\n- id: http\n  type: io.kestra.plugin.core.http.Request\n  auth:\n    type: digest\n    username: \"{{ secret('API_USER') }}\"\n    password: \"{{ secret('API_PASS') }}\"","handlingStrategy":"validation","validationCode":"String username = runContext.render(digestAuthConfiguration.getUsername()).as(String.class).orElse(null);\nString password = runContext.render(digestAuthConfiguration.getPassword()).as(String.class).orElse(null);\nif (StringUtils.isEmpty(username) || password == null) {\n  throw new IllegalStateException('Digest auth requires both username and password; check secret resolution');\n}","typeGuard":null,"tryCatchPattern":"try {\n  // build httpClientContext with digest creds\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains('username') || e.getMessage().contains('password')) {\n    log.error('Digest auth misconfigured: {}', e.getMessage());\n  }\n  throw e;\n}","preventionTips":["Provide both username and password for digest auth.","Verify secret expressions resolve to non-empty values.","Unit-test rendered credential values before the HTTP call."],"tags":["http-client","auth","digest","configuration","secrets"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}