Credential Expression preview shows undefined for JSON.parse($secrets...) but workflow execution succeeds

Hi,

I’m seeing a mismatch between the Credential Expression preview and actual workflow execution when using External Secrets (AWS Secrets Manager).

Environment

  • n8n version: 2.31.5 (self-hosted, queue mode)
  • External Secrets: AWS Secrets Manager, Authentication = Auto Detect
  • Vault name: camelCase only (hyphens were rejected by the UI validation)

What works

  1. Referencing a JSON secret as a whole in a Credential field Expression:

{{ $secrets.myVault[‘path/to/json-secret’] }}

→ Expression preview turns green / masked (resolved).

  1. Extracting a key with JSON.parse for Password (and other) fields:

{{ JSON.parse($secrets.myVault[‘path/to/json-secret’]).password }}

→ Workflow Execute succeeds (e.g. Postgres connects and returns the expected current_user / current_database).

Same pattern also worked with another JSON secret in the same vault.

The confusing part

In the Credential editor Expression preview, the JSON.parse(…) expressions show as:

undefined

even though the same Expression works at workflow runtime.

I also tried several variants in the preview (all showed undefined):

{{ JSON.parse($secrets.myVault[‘path/to/json-secret’]).password }}
{{ JSON.parse($secrets.myVault[“path/to/json-secret”]).password }}
{{ JSON.parse(String($secrets.myVault[‘path/to/json-secret’])).password }}
{{ JSON.parse($secrets.myVault[‘path/to/json-secret’])[‘password’] }}
{{ $secrets.myVault[‘path/to/json-secret’].password }}

Question

Is it expected that Credential Expression preview shows undefined for JSON.parse($secrets…) while execution still resolves the value correctly?

If yes, is there a recommended way to validate External Secret Expressions in the UI without relying on a full workflow run?

If no, is this a known UI bug?

Thanks!

Hey @hideto, while you wait for a response, here are some things that might help:

Suggested resources

Automatically matched to your question.

Docs:

Forum:

@solomon, @achamm, @barn4k - you’ve helped with similar issues before, can you take a look?

Automatically suggested by n8n’s community bot. It’s a pilot - please share feedback here.

This is consistent with a confirmed GitHub issue (#24581) where users on v2.x reported JSON.parse($secrets.awsSecretsManager["path/to/secret"]).field failing in the credential preview and sometimes in execution as well, after upgrading from v1 . Your case differs in that execution succeeds — which actually means your setup is working correctly.

This is a known behavior, as the preview environment often has limitations or different contexts compared to the actual workflow execution, especially when dealing with sensitive data like external secrets or environment variables.

Since there’s no in-editor validation path, here are your best options:

  1. Use a minimal test workflow — Add a Set node or Code node with {{ JSON.parse($secrets.myVault['path/to/json-secret']).password }} and run it manually. A green result confirms resolution works end-to-end.

  2. Split secrets at the AWS level — Store individual flat key-value secrets (e.g., myVault/db-password as a plain string) instead of a single JSON blob, so the credential field expression becomes simply {{ $secrets.myVault['myVault/db-password'] }} — no JSON.parse needed, and preview will resolve correctly.

  3. Treat preview as non-authoritative for JSON secrets — Since your execution already succeeds, the undefined preview is cosmetic noise. Document this behavior for your team so no one interprets it as a misconfiguration.

Does that help?

It’s not uncommon to see discrepancies between the Credential Expression preview and the actual workflow execution in n8n, especially when dealing with complex expressions like JSON parsing. The preview may not fully evaluate the expression context, which can lead to it showing “undefined” even though the workflow runs successfully. This behavior is generally expected due to how the preview feature works. It may not be able to access the full context or the actual data at the time of rendering, which can result in misleading outputs. Unfortunately, there isn’t a built-in way to validate External Secret Expressions in the UI without running the workflow, as the preview is limited in its capabilities. To work around this, you can create a simple test workflow that triggers the execution of the expression you want to validate. This way, you can confirm that your expression works as intended without needing to run your full workflow. If you suspect this might be a bug or if you consistently encounter issues, it could be worth checking the n8n GitHub repository for any reported issues or updates related to this behavior. Additionally, keeping your n8n version updated can help ensure you have the latest fixes and improvements

Thanks for letting us know about this, We have created CV-45 as the internal dev ticket to look into it.

Thanks for letting us know about this, We have created LIGO-894 as the internal dev ticket to look into it.

Hi @hideto
The editor never receives the secret value. $secrets resolves only in credential fields and the values are never displayed to the user, so the preview has no real string for JSON.parse to run against and returns undefined. n8n also only supports plaintext values for secrets, not JSON objects, so a parsed sub-key will not render in the preview even though resolution at execution time works.
To check a credential without a full workflow run, hit Save on the credential, n8n runs its own credential test server-side with the secret resolved. The same test is on the public API if you want it scripted:

POST /api/v1/credentials/{id}/test

It returns status OK or Error using the stored credential data.