dotnet/efcore · error · ArgumentException

The context class name

Error message

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

What it means

Thrown by ReverseEngineerScaffolder.ScaffoldModel when the supplied ContextName is present but is not a valid C# identifier or is a C# reserved keyword. The generated DbContext class name must be a legal identifier, so an invalid name is reported as ArgumentException (DesignStrings.ContextClassNotValidCSharpIdentifier).

Solutions

  1. Pass a context name that is a valid C# identifier and not a keyword (letters/underscores, does not start with a digit).
  2. If generating from a database name, sanitize it (strip invalid chars, prefix with a letter/underscore) before use.
  3. Omit --context to let EF derive a default valid name from the database.

Example fix

# before
dotnet ef dbcontext scaffold "..." Npgsql.EntityFrameworkCore.PostgreSQL --context my-context
# after
dotnet ef dbcontext scaffold "..." Npgsql.EntityFrameworkCore.PostgreSQL --context MyContext
Defensive patterns

Strategy: validation

Validate before calling

if (!string.IsNullOrWhiteSpace(options.ContextName)
    && (!IsValidCSharpIdentifier(options.ContextName) || IsCSharpKeyword(options.ContextName)))
    throw new ArgumentException($"'{options.ContextName}' is not a valid C# identifier.");
// helper:
static bool IsValidCSharpIdentifier(string s) =>
    s.Length > 0 && (char.IsLetter(s[0]) || s[0] == '_')
    && s.All(c => char.IsLetterOrDigit(c) || c == '_');

Type guard

static bool IsValidContextName(string name) => !string.IsNullOrWhiteSpace(name) && IsValidCSharpIdentifier(name) && !IsCSharpKeyword(name);

Try / catch

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

Prevention

When it happens

Trigger: Calling 'dotnet ef dbcontext scaffold' (or Scaffold-DbContext, or the API directly) with a --context value that starts with a digit, contains invalid characters (dashes, spaces), or equals a C# keyword like 'class' or 'static'.

Common situations: Deriving the context name from a database name with dashes/underscores handled incorrectly; passing a keyword by accident; automated tooling that passes unsanitized database names as context names.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/f429064d06b594b6. Report an issue: GitHub.

Appendix: 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 3a2006ef56)