{"record":{"id":"c4df69567b647484","repo":"elsa-workflows/elsa-core","slug":"secret-reference-name-is-not-compatible-with-required-type","errorCode":null,"errorMessage":"Secret '{reference.Name}' is not compatible with required type '{reference.TypeName}'.","messagePattern":"Secret '(.+?)' is not compatible with required type '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Secrets/Services/DefaultSecretResolver.cs","lineNumber":14,"sourceCode":"namespace Elsa.Secrets.Services;\n\npublic class DefaultSecretResolver(ISecretManager secretManager) : ISecretResolver\n{\n    public Task<string> ResolveAsync(string name, CancellationToken cancellationToken = default) => ResolveAsync(new SecretReference(name), cancellationToken);\n\n    public async Task<string> ResolveAsync(SecretReference reference, CancellationToken cancellationToken = default)\n    {\n        var secret = await secretManager.GetAsync(reference.Name, cancellationToken);\n        if (secret == null)\n            throw new InvalidOperationException($\"Secret '{reference.Name}' was not found.\");\n\n        if (!string.IsNullOrWhiteSpace(reference.TypeName) && !string.Equals(secret.TypeName, reference.TypeName, StringComparison.OrdinalIgnoreCase))\n            throw new InvalidOperationException($\"Secret '{reference.Name}' is not compatible with required type '{reference.TypeName}'.\");\n\n        if (!string.IsNullOrWhiteSpace(reference.Scope) && !string.Equals(secret.Scope, reference.Scope, StringComparison.OrdinalIgnoreCase))\n            throw new InvalidOperationException($\"Secret '{reference.Name}' is not compatible with required scope '{reference.Scope}'.\");\n\n        var payload = await secretManager.ResolvePayloadAsync(secret, cancellationToken);\n        return payload.Value!;\n    }\n}\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Secrets/Services/DefaultSecretResolver.cs#L1-L23","documentation":"ResolveAsync optionally validates that the secret's TypeName matches the SecretReference.TypeName (case-insensitive) and throws InvalidOperationException on mismatch. This guards against binding a secret to code expecting a different secret type/schema. It fires only when a TypeName was specified on the reference.","triggerScenarios":"Resolving a SecretReference with TypeName set (e.g. 'ConnectionString') while the stored secret's TypeName is different or null.","commonSituations":"Secret recreated without its type metadata; reference copied from another secret; type naming changed between versions; migration dropped TypeName.","solutions":["Update the reference TypeName to match the stored secret's TypeName.","Recreate/update the secret with the expected TypeName.","Remove TypeName from the reference if type enforcement is not required.","Fix migrations/creation code so TypeName is persisted."],"exampleFix":"// before\nvar value = await resolver.ResolveAsync(new SecretReference(\"ApiKey\", typeName: \"HttpApiKey\"));\n// after\nvar value = await resolver.ResolveAsync(new SecretReference(\"ApiKey\", typeName: \"ApiKey\")); // matches secret.TypeName","handlingStrategy":"validation","validationCode":"var secret = await secretManager.GetAsync(reference.Name, ct);\nif (secret is not null && !string.IsNullOrEmpty(reference.TypeName) &&\n    !string.Equals(secret.TypeName, reference.TypeName, StringComparison.OrdinalIgnoreCase))\n    throw new InvalidOperationException($\"Type mismatch for secret '{reference.Name}'.\");","typeGuard":"bool TypeMatches(Secret? s, string? expected) =>\n    string.IsNullOrEmpty(expected) || string.Equals(s?.TypeName, expected, StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try { var value = await resolver.ResolveAsync(reference, ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not compatible with required type\")) { logger.LogError(\"Secret {Name} has wrong type: {Msg}\", reference.Name, ex.Message); throw; }","preventionTips":["Always set TypeName when creating typed secrets","Keep type names in shared constants","Validate type after migrations/imports"],"tags":["secrets","type-mismatch","validation"],"backgroundTag":"type-mismatch","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}