{"record":{"id":"ecd4863391edfb96","repo":"kestra-io/kestra","slug":"cannot-find-secret-for-key-key","errorCode":null,"errorMessage":"Cannot find secret for key '{key}'.","messagePattern":"Cannot find secret for key '(.+?)'\\.","errorType":"exception","errorClass":"SecretNotFoundException","httpStatus":404,"severity":"error","filePath":"core/src/main/java/io/kestra/core/secret/SecretService.java","lineNumber":55,"sourceCode":"                try {\n                    String value = entry.getValue().replaceAll(\"\\\\R\", \"\");\n                    consumer.accept(Map.entry(entry.getKey(), new String(Base64.getDecoder().decode(value))));\n                } catch (Exception e) {\n                    log.error(\"Could not decode secret '{}', make sure it is Base64-encoded: {}\", entry.getKey(), e.getMessage());\n                }\n            })\n            .collect(\n                Collectors.toMap(\n                    entry -> entry.getKey().substring(SECRET_PREFIX.length()).toUpperCase(),\n                    Map.Entry::getValue\n                )\n            );\n    }\n\n    public String findSecret(String tenantId, String namespace, String key) throws SecretNotFoundException, IOException {\n        String secret = decodedSecrets.get(key.toUpperCase());\n        if (secret == null) {\n            throw new SecretNotFoundException(\"Cannot find secret for key '\" + key + \"'.\");\n        }\n        return secret;\n    }\n\n    /**\n     * Finds the secret in full mode, as a value plus metadata.\n     * The default returns the value with empty metadata. Multi-field secret managers override this to add metadata.\n     */\n    public SecretObject findSecretObject(String tenantId, String namespace, String key) throws SecretNotFoundException, IOException {\n        return new SecretObject(findSecret(tenantId, namespace, key));\n    }\n\n    public ArrayListTotal<META> list(Pageable pageable, String tenantId, List<QueryFilter> filters) throws IOException {\n        final Predicate<String> queryPredicate = filters.stream()\n            .filter(filter -> QueryFilter.Field.QUERY.equals(filter.field()) && filter.value() != null)\n            .findFirst()\n            .map(filter ->\n            {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/secret/SecretService.java#L37-L73","documentation":"The `SecretService.findSecret()` method looks up a secret by its key (case-insensitive, uppercased) in the in-memory `decodedSecrets` map. This map is populated at startup from environment variables prefixed with `SECRET_`. If no matching key exists, a `SecretNotFoundException` is thrown. This is a runtime/infrastructure error, not a code error.","triggerScenarios":"Referencing `{{ secret('MY_KEY') }}` in a flow when no `SECRET_MY_KEY` environment variable is set. The secret was deleted from the environment or the variable name has a typo. The secret exists but under a different tenant or namespace (in multi-tenant setups with custom secret managers).","commonSituations":"Secrets are set in a local `.env` file but not loaded into the running process. In Docker/k8s deployments the secret env var was not mounted into the container. A secret key has a typo or case mismatch (the lookup uppercases the key, but the env var prefix must be `SECRET_`).","solutions":["Verify the secret environment variable is set with the exact prefix: `SECRET_MY_KEY` for key `MY_KEY`.","Ensure the value is Base64-encoded (the service decodes it; a raw value will fail silently at decode time and the key will be absent).","Check that the env var is actually present in the running process (`env | grep SECRET_`).","In Docker/k8s, verify the secret is mounted as an env var in the container spec.","Confirm there is no tenant/namespace mismatch if using a custom secret manager."],"exampleFix":"# before: secret missing from env\n{{ secret('API_KEY') }}\n# fix: set the env var with Base64-encoded value\nexport SECRET_API_KEY=$(echo -n 'my-secret-value' | base64)","handlingStrategy":"try-catch","validationCode":"// Check if secret key exists before calling findSecret\nimport io.kestra.core.secret.SecretService;\n\npublic static String getSecretOrEmpty(SecretService service, String tenantId, String namespace, String key) {\n    try {\n        return service.findSecret(tenantId, namespace, key);\n    } catch (SecretNotFoundException e) {\n        return null; // or throw a more descriptive error\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    String secret = secretService.findSecret(tenantId, namespace, key);\n} catch (SecretNotFoundException e) {\n    log.error(\"Secret '{}' not found. Ensure SECRET_{} env var is set and Base64-encoded.\", key, key.toUpperCase());\n    throw e;\n}","preventionTips":["Verify secrets are set with `env | grep SECRET_` in the running process.","Ensure secret values are Base64-encoded in the environment variable.","Document required secret keys in the flow or README.","Use a secrets management checklist for deployments.","In Docker/k8s, verify secrets are mounted as env vars in the container spec."],"tags":["secret","configuration","environment","not-found"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}