dotnet/efcore · error · ArgumentException

The context class name '{contextClassName}' is not a valid C

Error message

The context class name '{contextClassName}' is not a valid C# Identifier.

What it means

Thrown in ReverseEngineerScaffolder.ScaffoldModel (line 77, resource ContextClassNotValidCSharpIdentifier) when the supplied context name is not a valid C# identifier or is a C# keyword. EF must emit a class with that name, so it validates via IsValidIdentifier and IsCSharpKeyword; failing either throws ArgumentException before any database work. Only checked when ContextName is non-blank.

Source

Thrown at src/EFCore.Design/Scaffolding/Internal/ReverseEngineerScaffolder.cs:77

    private IModelCodeGeneratorSelector ModelCodeGeneratorSelector { get; }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual ScaffoldedModel ScaffoldModel(
        string connectionString,
        DatabaseModelFactoryOptions databaseOptions,
        ModelReverseEngineerOptions modelOptions,
        ModelCodeGenerationOptions codeOptions)
    {
        if (!string.IsNullOrWhiteSpace(codeOptions.ContextName)
            && (!_cSharpUtilities.IsValidIdentifier(codeOptions.ContextName)
                || _cSharpUtilities.IsCSharpKeyword(codeOptions.ContextName)))
        {
            throw new ArgumentException(
                DesignStrings.ContextClassNotValidCSharpIdentifier(codeOptions.ContextName));
        }

        var resolvedConnectionString = _connectionStringResolver.ResolveConnectionString(connectionString);
        if (resolvedConnectionString != connectionString)
        {
            codeOptions.SuppressConnectionStringWarning = true;
        }
        else if (!codeOptions.SuppressOnConfiguring)
        {
            _reporter.WriteWarning(DesignStrings.SensitiveInformationWarning);
        }

        codeOptions.ConnectionString ??= connectionString;

        var databaseModel = _databaseModelFactory.Create(resolvedConnectionString, databaseOptions);
        var modelConnectionString = (string?)databaseModel[ScaffoldingAnnotationNames.ConnectionString];
        if (!string.IsNullOrEmpty(modelConnectionString))

View on GitHub (pinned to dbf9771522)

Solutions

  1. Choose a context name composed of letters/digits/underscores that starts with a letter or underscore (e.g. 'ShopContext').
  2. Avoid C# reserved keywords as the context name.
  3. If the name is derived programmatically, sanitize it (strip illegal chars, prefix with underscore) before passing it in.
  4. Leave ContextName blank to let ReverseEngineerScaffolder derive a valid default from the database name.

Example fix

// before: illegal context name
dotnet ef dbcontext scaffold "..." SqlServer --context My-Context

// after: valid identifier
dotnet ef dbcontext scaffold "..." SqlServer --context MyContext
Defensive patterns

Strategy: validation

Validate before calling

// Validate the context name before scaffolding
var utils = new CSharpUtilities();
if (!string.IsNullOrWhiteSpace(name)
    && (!utils.IsValidIdentifier(name) || utils.IsCSharpKeyword(name)))
    throw new ArgumentException($"'{name}' is not a valid C# identifier.");

Type guard

static bool IsValidContextName(string name)
    => !string.IsNullOrWhiteSpace(name)
       && System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(name)
       && !CSharpKeywords.Contains(name);

Try / catch

try { scaffolder.ScaffoldModel(...); }
catch (ArgumentException ex) when (ex.Message.Contains("valid C# identifier"))
{ /* sanitize the name (strip invalid chars, prefix underscore) and retry */ }

Prevention

When it happens

Trigger: Calling ScaffoldModel (or 'dotnet ef dbcontext scaffold --context <name>') with a ContextName that contains invalid identifier characters, starts with a digit, or equals a reserved keyword. The condition `!IsValidIdentifier || IsCSharpKeyword` is true and throws ContextClassNotValidCSharpIdentifier(ContextName).

Common situations: Passing a context name with spaces, dots, hyphens, or special characters (e.g. 'My-Context', '1Context'). Using a C# keyword as the name (e.g. 'class', 'event', 'namespace'). Deriving the name from a database/schema name with illegal characters without sanitizing.

Related errors


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