Unity-Technologies/UnityCsReference · error · Exception

Id must be a number (line: ' ')

Error message

Id must be a number (line: '{line}')

What it means

Thrown when the rule id (the text after ':' up to the first '|') cannot be parsed as an Int32. Restricted API rule ids must be numeric so they can be used as dictionary keys and for override matching.

Solutions

  1. Change the id to an integer, e.g. ':1001 | signature | error'.
  2. Ensure ids are unique and numeric across the file.

Example fix

// before
:FILE_OPEN | System.IO.File::Open | error
// after
:1001 | System.IO.File::Open | error
Defensive patterns

Strategy: validation

Validate before calling

// Rule ids must be integers.
var id = token.Slice(1); // after ':'
if (!Int32.TryParse(id, out _))
    throw new FormatException($"Rule id is not a number: '{line}'");

Try / catch

try { config = RestrictedApisConfig.Load(path); }
catch (Exception ex) when (ex.Message.Contains("Id must be a number"))
{ /* replace the non-numeric id with an integer */ }

Prevention

When it happens

Trigger: A rule line whose ':id' token is non-numeric, e.g. ':abc | signature | error'.

Common situations: Using a string/label as an id, typos, or copy-paste from a non-numeric identifier scheme.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/8b37dce42b5f1ddd. Report an issue: GitHub.

Appendix: source

Thrown at Editor/Mono/Scripting/RestrictedApisValidation/RestrictedApisConfig.cs:177

        var signature = NextToken(ref lineSpan, out separatorIndex);
        if (separatorIndex == -1)
            throw new Exception($"Invalid severity '' in line '{line}'");

        var severitySpan = NextToken(ref lineSpan, out separatorIndex);
        var description = "";
        var documentationUrl = "";
        if (separatorIndex != -1)
        {
            description = NextToken(ref lineSpan,  out separatorIndex).ToString();
            if (separatorIndex != -1)
            {
                documentationUrl = NextToken(ref lineSpan,  out separatorIndex).ToString();
            }
        }

        if (!Int32.TryParse(id, out var intId))
        {
            throw new Exception($"Id must be a number (line: '{line}')");
        }

        int referenceHashCode;
        var isTypeSignature = false;
        if (signature.Length == 0)
        {
            if (!_idToSignatureDetails.TryGetValue(intId, out var previousMappedId))
                throw new Exception($"Id ({intId}) overriden in configuration line '{line}' is not defined by any previous lines.");

            (referenceHashCode, isTypeSignature)  = previousMappedId;
        }
        else
        {
            isTypeSignature = line.AsSpan().IndexOf("::") == -1; // member signatures must have a :: as a declaring type name/member name separator

            //TODO: When we switch from netstandard to *any* .NET BCL, remove the ToString() and call String.GetHashCode(signature) : https://learn.microsoft.com/en-us/dotnet/api/system.string.gethashcode?view=net-9.0#system-string-gethashcode(system-readonlyspan((system-char)))
            referenceHashCode = signature.ToString().GetHashCode();
            _idToSignatureDetails[intId] = new (referenceHashCode, isTypeSignature);

View on GitHub (pinned to 225b0fbdb5)