git-ecosystem/git-credential-manager · error · ArgumentException

State key cannot start with

Error message

State key cannot start with '{GcmStatePrefix}'; the prefix is reserved and added automatically when state is emitted.

What it means

The 'gcm-' state prefix (Constants.CredentialProtocol.GcmStatePrefix) is reserved: it is added automatically when state is emitted on the wire, so user-supplied keys must be stored WITHOUT the prefix. Passing a key that already starts with the prefix would double-prefix it, so ValidateKey throws ArgumentException.

Solutions

  1. Strip the prefix before storing: key.StartsWith(prefix) ? key.Substring(prefix.Length) : key.
  2. Pass only the bare suffix as the state key; the library adds the prefix on emission.
  3. Normalize state keys on ingestion when reading them back from a previous response.

Example fix

// before
response.SetState("gcm-oauth-round", "1");
// after
response.SetState("oauth-round", "1"); // prefix added automatically on emit
Defensive patterns

Strategy: validation

Validate before calling

if (key != null && key.StartsWith(Constants.CredentialProtocol.GcmStatePrefix, StringComparison.Ordinal))
    key = key.Substring(Constants.CredentialProtocol.GcmStatePrefix.Length);

Type guard

static string StripStatePrefix(string k) =>
    k != null && k.StartsWith(Constants.CredentialProtocol.GcmStatePrefix, StringComparison.Ordinal)
        ? k.Substring(Constants.CredentialProtocol.GcmStatePrefix.Length) : k;

Try / catch

try { response.SetState(key, value); }
catch (ArgumentException e) when (e.Message.Contains("prefix is reserved")) { response.SetState(StripStatePrefix(key), value); }

Prevention

When it happens

Trigger: Calling SetState/WithState with a key like 'gcm-foo' (or whatever GcmStatePrefix is) — typically because the developer saw emitted state lines prefixed and copied that form back in.

Common situations: Round-tripping state: reading an emitted state line (e.g. 'gcm-xyz=1') and feeding the full prefixed key back into SetState on a subsequent invocation instead of stripping the prefix.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/fd47bf6bb1bd42da. Report an issue: GitHub.

Appendix: source

Thrown at src/Core/GitStateValidation.cs:98

    {
        if (string.IsNullOrWhiteSpace(key))
        {
            throw new ArgumentException("State key cannot be null or whitespace.", nameof(key));
        }

        foreach (char c in key)
        {
            if (c == EQ || c == LF || c == NUL)
            {
                throw new ArgumentException(
                    "State key cannot contain '=', newline, or NUL characters.",
                    nameof(key));
            }
        }

        if (key.StartsWith(Constants.CredentialProtocol.GcmStatePrefix, StringComparison.Ordinal))
        {
            throw new ArgumentException(
                $"State key cannot start with '{Constants.CredentialProtocol.GcmStatePrefix}'; " +
                "the prefix is reserved and added automatically when state is emitted.",
                nameof(key));
        }
    }

    /// <summary>
    /// Throws <see cref="ArgumentException"/> if <paramref name="value"/> is
    /// not a legal state entry value.
    /// </summary>
    public static void ValidateValue(string value)
    {
        if (value is null)
        {
            throw new ArgumentNullException(nameof(value), "State value cannot be null.");
        }

        foreach (char c in value)

View on GitHub (pinned to e8ce762cd0)