mgth/LittleBigMouse · error · CryptographicException

Payload was protected with

Error message

Payload was protected with '{scheme}', unreadable on this system.

What it means

Envelopes are self-describing ('LBM1.<scheme>.<base64>'). Unprotect only understands 'dpapi' (on Windows) and 'aesgcm' (anywhere); any other scheme hits this default case and throws a CryptographicException naming the scheme. It exists so a payload carried to a machine that cannot read it fails loudly instead of silently decoding to garbage.

Solutions

  1. Re-create the secret on this machine: delete the stored envelope and re-enter/re-pair so Protect seals it with a scheme this system supports.
  2. If it is a dpapi envelope, open the data file on Windows (or with the same user account on Windows) and migrate the value to clear text or re-protect it there.
  3. If caused by a version downgrade, upgrade back to the version that wrote the envelope.
  4. Check the envelope string is intact (starts with 'LBM1.' followed by dpapi or aesgcm) in case the file was corrupted or truncated in transfer.

Example fix

// before
var token = protector.Unprotect(envelopeFromSyncedProfile); // dpapi envelope on Linux
// after
if (envelope.StartsWith("LBM1.dpapi.") && !OperatingSystem.IsWindows())
    token = RePairDevice(); // scheme unreadable here — obtain it fresh
else
    token = protector.Unprotect(envelope);
Defensive patterns

Strategy: type-guard

Validate before calling

static bool SchemeSupportedHere(string envelope) =>
    !SecretProtector.IsProtected(envelope) ||
    (envelope.StartsWith("LBM1.dpapi.") && OperatingSystem.IsWindows()) ||
    envelope.StartsWith("LBM1.aesgcm.");

Type guard

static bool IsReadableOnThisSystem(string envelope)
{
    if (!SecretProtector.IsProtected(envelope)) return true; // clear text
    var scheme = envelope[5..envelope.IndexOf('.')];
    return scheme switch
    {
        "dpapi" => OperatingSystem.IsWindows(),
        "aesgcm" => true,
        _ => false
    };
}

Try / catch

try { return protector.Unprotect(envelope); }
catch (CryptographicException ex) when (ex.Message.Contains("unreadable on this system"))
{ return ReCreateSecret(); /* scheme unsupported here */ }

Prevention

When it happens

Trigger: Calling Unprotect on an envelope whose scheme token is neither 'dpapi' nor 'aesgcm' — e.g. a 'dpapi' envelope from a Windows profile opened on Linux/macOS, an envelope produced by a newer version with an added scheme, or a hand-edited/corrupted scheme field.

Common situations: Syncing or copying the config directory between Windows and Unix machines; restoring a Windows-encrypted settings file on Linux; upgrading from a future version that introduced a new scheme and then downgrading; manual editing of the envelope string.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


AI-assisted analysis of mgth/LittleBigMouse@7a42f01d47 (2026-09-16). Data as JSON: /api/errors/4b0b4d1351c54327. Report an issue: GitHub.

Appendix: source

Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugins.Core/SecretProtector.cs:120

            case AesGcmScheme:
                if (payload.Length < NonceLength + TagLength)
                    throw new CryptographicException("Protected payload is truncated.");

                var plain = new byte[payload.Length - NonceLength - TagLength];
                using (var aes = new AesGcm(ReadKey() ?? throw new CryptographicException(
                           $"No key at {_keyFilePath} to read this payload with."), TagLength))
                {
                    aes.Decrypt(
                        payload.AsSpan(0, NonceLength),
                        payload.AsSpan(NonceLength + TagLength),
                        payload.AsSpan(NonceLength, TagLength),
                        plain);
                }
                return Encoding.UTF8.GetString(plain);

            default:
                throw new CryptographicException(
                    $"Payload was protected with '{scheme}', unreadable on this system.");
        }
    }

    byte[] GetOrCreateKey()
    {
        lock (_keyLock)
        {
            return _key ??= ReadKeyLocked() ?? CreateKeyLocked();
        }
    }

    byte[]? ReadKey()
    {
        lock (_keyLock)
        {
            return _key ??= ReadKeyLocked();
        }

View on GitHub (pinned to 7a42f01d47)