{"record":{"id":"202f39abc6394591","repo":"elsa-workflows/elsa-core","slug":"tenant-has-not-been-resolved","errorCode":null,"errorMessage":"Tenant has not been resolved.","messagePattern":"Tenant has not been resolved\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.Common/Multitenancy/Results/TenantResolverResult.cs","lineNumber":39,"sourceCode":"    /// <summary>\n    /// Creates a new instance of <see cref=\"TenantResolverResult\"/> representing a resolved tenant.\n    /// </summary>\n    /// <param name=\"tenantId\">The resolved tenant.</param>\n    /// <returns>A new instance of <see cref=\"TenantResolverResult\"/> representing a resolved tenant.</returns>\n    public static TenantResolverResult Resolved(string? tenantId) => new(tenantId, true);\n\n    /// <summary>\n    /// Creates a new instance of <see cref=\"TenantResolverResult\"/> representing an unresolved tenant.\n    /// </summary>\n    /// <returns>A new instance of <see cref=\"TenantResolverResult\"/> representing an unresolved tenant.</returns>\n    public static TenantResolverResult Unresolved() => new(null, false);\n\n    /// <summary>\n    /// Gets a value indicating whether the tenant has been resolved.\n    /// </summary>\n    public bool IsResolved => _isResolved;\n\n    public string ResolveTenantId() => TenantId ?? throw new InvalidOperationException(\"Tenant has not been resolved.\");\n}","sourceCodeStart":21,"sourceCodeEnd":40,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.Common/Multitenancy/Results/TenantResolverResult.cs#L21-L40","documentation":"A sentinel guard on TenantResolverResult: accessing the resolved tenant (the TenantId getter) when the result was produced by the Unresolved factory (IsResolved = false) throws. It signals a programming error — the caller failed to check whether a tenant was resolved before reading the tenant id.","triggerScenarios":"Calling ResolveTenantId on a result whose IsResolved is false — i.e. the resolver could not determine a tenant (no tenant resolver matched, no header/cookie/API key identified a tenant).","commonSituations":"Requesting Elsa APIs without tenant-identifying headers in multi-tenant mode; misconfigured tenant resolvers; background/hosted code executing outside the HTTP pipeline where no resolution ran.","solutions":["Check IsResolved before calling ResolveTenantId and handle the unresolved case explicitly.","Configure a tenant resolver (header, cookie, etc.) appropriate for your requests in multi-tenant mode.","Provide a default/ambient tenant provider for non-HTTP execution contexts.","Log the resolver pipeline to see why no tenant matched."],"exampleFix":"// before\nvar tenantId = result.ResolveTenantId();\n// after\nif (!result.IsResolved) throw new BadRequestException(\"Tenant header missing\");\nvar tenantId = result.ResolveTenantId();","handlingStrategy":"type-guard","validationCode":"if (!result.IsResolved)\n    throw new UnauthorizedAccessException(\"No tenant could be resolved from the request.\");","typeGuard":"bool TryResolveTenantId(TenantResolverResult result, out string? tenantId) { tenantId = result.IsResolved ? result.TenantId : null; return result.IsResolved; }","tryCatchPattern":"try { tenantId = result.ResolveTenantId(); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Tenant has not been resolved.\") { httpContext.Response.StatusCode = 400; }","preventionTips":["Configure tenant resolvers before enabling multi-tenancy","Test requests both with and without tenant headers","Provide an explicit default tenant for background/non-HTTP work"],"tags":["multitenancy","tenant-resolution","dotnet"],"backgroundTag":"missing-required-config","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}