dotnet/efcore · error · InvalidOperationException

The requested configuration is not stored in the read-optimi

Error message

The requested configuration is not stored in the read-optimized model, please use 'DbContext.GetService<IDesignTimeModel>().Model'.

What it means

GetVectorIndexType() reads the Cosmos vector-index-type annotation from an index. The read-optimized runtime model (RuntimeIndex) deliberately omits design-time-only annotations to stay lean, so calling it on a RuntimeIndex throws InvalidOperationException via CoreStrings.RuntimeModelMissingData and directs you to the design-time model instead. Use DbContext.GetService<IDesignTimeModel>().Model for any annotation/configuration-source inspection.

Source

Thrown at src/EFCore.Cosmos/Extensions/CosmosIndexExtensions.cs:26

/// <summary>
///     Index extension methods for Azure Cosmos DB-specific metadata.
/// </summary>
/// <remarks>
///     See <see href="https://aka.ms/efcore-docs-modeling">Modeling entity types and relationships</see>, and
///     <see href="https://aka.ms/efcore-docs-cosmos">Accessing Azure Cosmos DB with EF Core</see> for more information and examples.
/// </remarks>
public static class CosmosIndexExtensions
{
    /// <summary>
    ///     Returns the vector index type to use, such as "flat", "diskANN", or "quantizedFlat".
    ///     See <see href="https://aka.ms/ef-cosmos-vectors">Vector Search in Azure Cosmos DB for NoSQL</see> for more information.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <returns>The index type to use, or <see langword="null" /> if none is set.</returns>
    public static VectorIndexType? GetVectorIndexType(this IReadOnlyIndex index)
        => (index is RuntimeIndex)
            ? throw new InvalidOperationException(CoreStrings.RuntimeModelMissingData)
            : (VectorIndexType?)index[CosmosAnnotationNames.VectorIndexType];

    /// <summary>
    ///     Sets the vector index type to use, such as "flat", "diskANN", or "quantizedFlat".
    ///     See <see href="https://aka.ms/ef-cosmos-vectors">Vector Search in Azure Cosmos DB for NoSQL</see> for more information.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <param name="indexType">The index type to use.</param>
    public static void SetVectorIndexType(this IMutableIndex index, VectorIndexType? indexType)
        => index.SetOrRemoveAnnotation(CosmosAnnotationNames.VectorIndexType, indexType);

    /// <summary>
    ///     Sets the vector index type to use, such as "flat", "diskANN", or "quantizedFlat".
    ///     See <see href="https://aka.ms/ef-cosmos-vectors">Vector Search in Azure Cosmos DB for NoSQL</see> for more information.
    /// </summary>
    /// <param name="index">The index.</param>
    /// <param name="indexType">The index type to use.</param>
    /// <param name="fromDataAnnotation">Indicates whether the configuration was specified using a data annotation.</param>

View on GitHub (pinned to dbf9771522)

Solutions

  1. Obtain the index from the design-time model: var dt = dbContext.GetService<IDesignTimeModel>().Model; then navigate to the index and call GetVectorIndexType().
  2. Never read design-time-only annotations (VectorIndexType, configuration sources) from DbContext.Model; treat the runtime model as read-optimized.
  3. If you must branch on annotation presence at runtime, guard with `index is not RuntimeIndex` before calling.

Example fix

// before (runtime model throws)
var t = context.Model
    .FindEntityType(typeof(Item))!.GetIndexes().First().GetVectorIndexType();

// after (design-time model)
var dtModel = context.GetService<IDesignTimeModel>().Model;
var t = dtModel
    .FindEntityType(typeof(Item))!.GetIndexes().First().GetVectorIndexType();
Defensive patterns

Strategy: validation

Validate before calling

// Guard before reading a design-time-only annotation.
if (index is RuntimeIndex)
{
    var dtIndex = context.GetService<IDesignTimeModel>().Model
        .FindEntityType(entityType)!.GetIndexes().ElementAt(i);
    return dtIndex.GetVectorIndexType();
}
return index.GetVectorIndexType();

Type guard

static bool IsRuntimeIndex(IReadOnlyIndex index) => index is RuntimeIndex;

Try / catch

try { return index.GetVectorIndexType(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("read-optimized model"))
{ return context.GetService<IDesignTimeModel>().Model /* navigate to index */ .GetVectorIndexType(); }

Prevention

When it happens

Trigger: Calling index.GetVectorIndexType() where the index was obtained by navigating DbContext.Model (the runtime/cached model) — e.g. metadata inspection code, diagnostics, or a compiled-model path that hands back a RuntimeIndex.

Common situations: Building tooling/migrations that read index metadata at runtime; assuming DbContext.Model and the design-time model are equivalent; iterating model.GetEntityTypes().SelectMany(e => e.GetIndexes()) and reading Cosmos annotations.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/060f88b8772a294a. Report an issue: GitHub.