{"record":{"id":"25c4c77ffc4314e2","repo":"kestra-io/kestra","slug":"failed-to-read-secret-sub-key-s-from-secret-s","errorCode":null,"errorMessage":"Failed to read secret sub-key '%s' from secret '%s'. Ensure the secret contains valid JSON value.","messagePattern":"Failed to read secret sub-key '(.+?)' from secret '(.+?)'\\. Ensure the secret contains valid JSON value\\.","errorType":"exception","errorClass":"SecretException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/pebble/functions/SecretFunction.java","lineNumber":103,"sourceCode":"                    secretObject.metadata().values().forEach(value -> consumeSecret(context, value));\n                    result.put(METADATA_KEY, secretObject.metadata());\n                }\n                return result;\n            }\n\n            String secret = secretService.get().findSecret(flowTenantId, namespace, key);\n\n            if (subkey != null && !subkey.isEmpty()) {\n                try {\n                    JsonNode subkeys = OBJECT_MAPPER.readTree(secret);\n                    if (!subkeys.has(subkey)) {\n                        throw new SecretNotFoundException(\"Cannot find secret sub-key '\" + subkey + \"' in secret '\" + key + \"'.\");\n                    } else {\n                        JsonNode jsonNode = subkeys.get(subkey);\n                        secret = jsonNode.isValueNode() ? jsonNode.asText() : jsonNode.toString();\n                    }\n                } catch (JsonProcessingException e) {\n                    throw new SecretException(\n                        String.format(\n                            \"Failed to read secret sub-key '%s' from secret '%s'. Ensure the secret contains valid JSON value.\",\n                            subkey,\n                            key\n                        )\n                    );\n                }\n            }\n\n            consumeSecret(context, secret);\n            return secret;\n        } catch (SecretException | IOException e) {\n            throw new PebbleException(e, e.getMessage(), lineNumber, self.getName());\n        }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private void consumeSecret(EvaluationContext context, String value) {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/pebble/functions/SecretFunction.java#L85-L121","documentation":"When the secret() function is called with a 'subkey' argument, it attempts to parse the secret value as JSON using Jackson ObjectMapper.readTree(). If the secret is not valid JSON (e.g., a plain string, a number, or malformed JSON), a JsonProcessingException is caught and re-thrown as a SecretException with this message. This means the secret was found but its content cannot be interpreted as a JSON object for sub-key extraction.","triggerScenarios":"Calling {{ secret('API_TOKEN', subkey='key') }} when the secret value is a plain string like 'sk-abc123' (not JSON). The secret was stored as a raw value rather than a JSON object. The secret value contains truncated or corrupted JSON.","commonSituations":"Secret originally stored as a single value (token, password) but later accessed with a subkey as if it were a JSON object. Secret migration from one backend to another that changed the format. A team member stored a secret without JSON structure.","solutions":["If the secret is a single value, access it without subkey: {{ secret('API_TOKEN') }}.","If you need sub-key access, re-store the secret as a JSON object: {\"key\":\"sk-abc123\"}.","Verify the secret content in the secret backend to confirm it is valid JSON."],"exampleFix":"# before — secret value is a plain string, not JSON\n{{ secret('API_TOKEN', subkey='key') }}\n\n# after — access the raw value directly\n{{ secret('API_TOKEN') }}\n# or re-store as JSON: {\"key\":\"sk-abc123\"}\n{{ secret('API_TOKEN', subkey='key') }}","handlingStrategy":"validation","validationCode":"# Only use subkey on secrets known to contain valid JSON.\n# If unsure, access the raw value first:\n# {{ secret('MY_KEY') }}\n# If the value is not JSON, re-store it as JSON in the secret backend before using subkey.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store structured secrets as JSON objects from the start.","Verify secret content format in the secret backend before coding subkey access.","For single-value secrets (tokens, passwords), never use the subkey argument.","Add a comment in the flow noting which secrets are JSON and which are plain values."],"tags":["pebble","secret","subkey","json","parse-error"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}