Dokploy/dokploy · error · Error

AWS Secrets Manager: secret

Error message

AWS Secrets Manager: secret "${secretId}" is not JSON, cannot extract field "${field}"

What it means

When a vault ref includes a field (mysecret:password), getSecrets must JSON.parse the secret string to extract it. If the secret isn't valid JSON (plain text, YAML, base64), parsing fails and this error is thrown.

Solutions

  1. Store the secret as a JSON object: {"password":"s3cr3t!"} and keep the :password field ref
  2. Or drop the field suffix and reference the whole secret by name if it's a single value

Example fix

# before
aws secretsmanager put-secret-value --secret-id db --secret-string 's3cr3t!'
# ref: db:password

# after
aws secretsmanager put-secret-value --secret-id db --secret-string '{"password":"s3cr3t!"}'
# ref: db:password
Defensive patterns

Strategy: validation

Validate before calling

const probe = JSON.parse(await getSecretString(secretId)); // fails early with clear cause
if (typeof probe !== 'object') throw new Error('Secret must be a JSON object to use field refs');

Type guard

const isJsonObjectSecret = (s: string): boolean => {
  try { return typeof JSON.parse(s) === 'object' && JSON.parse(s) !== null; } catch { return false; }
};

Try / catch

try {
  await vault.getSecrets([`mysecret:field`]);
} catch (e) {
  if (/is not JSON/.test(String(e))) {
    // rewrite secret as JSON object, or drop the :field suffix
  }
}

Prevention

When it happens

Trigger: Setting ref 'db:password' where secret 'db' contains 's3cr3t!' (plain string, not JSON object).

Common situations: Storing a single password as plain text but referencing it with a :field suffix; storing YAML/env-file formatted secrets.

Related errors


AI-assisted analysis of Dokploy/dokploy@546686ea35 (2026-08-27). Data as JSON: /api/errors/b7e642bfc830a185. Report an issue: GitHub.

Appendix: source

Thrown at packages/server/src/utils/vault/aws.ts:70

					);
				}
				secretStrings.set(secretId, response.SecretString);
			}),
		);

		const result: Record<string, string> = {};
		for (const ref of refs) {
			const { secretId, field } = parseRef(ref);
			const secretString = secretStrings.get(secretId) as string;
			if (field === null) {
				result[ref] = secretString;
				continue;
			}
			let parsed: Record<string, unknown>;
			try {
				parsed = JSON.parse(secretString);
			} catch {
				throw new Error(
					`AWS Secrets Manager: secret "${secretId}" is not JSON, cannot extract field "${field}"`,
				);
			}
			const value = parsed[field];
			if (value === undefined || value === null) {
				throw new Error(
					`AWS Secrets Manager: field "${field}" not found in secret "${secretId}"`,
				);
			}
			result[ref] = typeof value === "string" ? value : JSON.stringify(value);
		}
		return result;
	},

	async testConnection(config) {
		const client = createClient(config);
		await client.send(new ListSecretsCommand({ MaxResults: 1 }));
	},

View on GitHub (pinned to 546686ea35)