tursodatabase/turso · error · ArgumentOutOfRangeException

Invalid value {value} for enum type {enumType}.

Error message

Invalid value {value} for enum type {enumType}.

What it means

ArgumentOutOfRangeException thrown by GetEnum<TEnum> when reading an enum-typed option (Mode, Cache, DateTimeKind): the stored value is already a TEnum instance but its numeric value is not defined on the enum. This only happens when an undefined enum value was placed into the underlying store through a path that bypassed the setter's converter, for example direct DbConnectionStringBuilder access or reflection. Normal string parsing in this getter deliberately skips the IsDefined check, so the typed-value branch is the guarded one.

Source

Thrown at bindings/dotnet/src/Turso.Data.Sqlite/SqliteConnectionStringBuilder.cs:270

    }

    private int GetInt(string keyword, int defaultValue)
    {
        return base.TryGetValue(keyword, out var value)
            ? Convert.ToInt32(value, CultureInfo.InvariantCulture)
            : defaultValue;
    }

    private TEnum GetEnum<TEnum>(string keyword, TEnum defaultValue)
        where TEnum : struct
    {
        if (!base.TryGetValue(keyword, out var value))
            return defaultValue;

        if (value is TEnum typedValue)
        {
            if (!Enum.IsDefined(typeof(TEnum), typedValue))
                throw new ArgumentOutOfRangeException(nameof(value), value, Properties.Resources.InvalidEnumValue(typeof(TEnum), typedValue));

            return typedValue;
        }

        if (value is string stringValue && Enum.TryParse<TEnum>(stringValue, ignoreCase: true, out var parsedValue))
            return parsedValue;

        return (TEnum)Enum.ToObject(typeof(TEnum), Convert.ToInt32(value, CultureInfo.InvariantCulture));
    }

    private void SetNullable<T>(string keyword, T? value)
        where T : struct
    {
        if (value.HasValue)
            this[keyword] = value.Value;
        else
            Remove(keyword);
    }

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Set enum options through the strongly-typed properties (builder.Mode = SqliteOpenMode.ReadOnly) so values are converted and validated on write.
  2. If you must write raw objects, validate first with Enum.IsDefined(typeof(SqliteOpenMode), value) before storing.
  3. Reset the suspect keyword (builder.Remove("Mode")) so the getter returns its default instead of the poisoned stored value.

Example fix

// before
((DbConnectionStringBuilder)builder)["Mode"] = (SqliteOpenMode)99;
var mode = builder.Mode; // throws: 99 not defined

// after
builder.Mode = SqliteOpenMode.ReadWriteCreate; // validated on write
Defensive patterns

Strategy: validation

Validate before calling

if (rawValue is SqliteOpenMode m && !Enum.IsDefined(m))
    throw new ConfigException($"Mode value {m} is not defined.");
builder.Mode = (SqliteOpenMode)Enum.ToObject(typeof(SqliteOpenMode), Enum.IsDefined(m) ? m : SqliteOpenMode.ReadWriteCreate);

Type guard

static bool IsValidEnum<TEnum>(object? v) where TEnum : struct, Enum
    => v is TEnum e && Enum.IsDefined(e);

Try / catch

try { var mode = builder.Mode; }
catch (ArgumentOutOfRangeException) { builder.Remove("Mode"); mode = SqliteOpenMode.ReadWriteCreate; }

Prevention

When it happens

Trigger: Storing an unvalidated boxed enum such as ((DbConnectionStringBuilder)builder)["Mode"] = (SqliteOpenMode)99 (or via reflection) and then reading builder.Mode; interop code that injects raw object values into the keyword table; values persisted from a version that defined different enum members.

Common situations: Configuration systems that write raw objects into DbConnectionStringBuilder; deserializing settings dictionaries into the builder without conversion; version drift where a stored numeric enum value no longer maps to a defined member.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/3c85a2ddb2b35253. Report an issue: GitHub.