{"record":{"id":"93689fa7a2d02cb6","repo":"Unity-Technologies/UnityCsReference","slug":"key-must-be-non-null-between-1-and-127-characters","errorCode":null,"errorMessage":"Key must be non-null, between 1 and 127 characters, and be a valid XML tag.","messagePattern":"Key must be non-null, between 1 and 127 characters, and be a valid XML tag\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/EditorDialog.cs","lineNumber":202,"sourceCode":"        }\n\n        private static void ThrowIfInvalidKey(string optOutKey)\n        {\n            // We want to ensure that the key string is a valid XML tag.\n            // More technically, we could restrict it to whichever is more restrictive of\n            // XML tags (Linux), Windows Registry key names, or NSPreference dictionaries\n            // (which are all valid XML tags), but this will simplify the validation for API users.\n            // Our EditorPrefs are stored in the registry, with this key as the path.\n            // The maximum length of a registry key is 255 characters, so we limit the key\n            // to account for the \"Software\\Unity Technologies\\Unity Editor 5.x Automated Testing\\\" prefix and a 12 character suffix.\n            // We also prefix the key with \"DialogOptOut.\" (13 chars) to ensure that it is unique to the dialog box API.\n            // For this reason, we will limit to a safer ~ 127 character limit.\n\n            // This regular expression ensures that the key string:\n            // Contains only alphanumeric characters, periods, underscores, and hyphens.\n            // Is between 1 and 127 characters long.\n            if (string.IsNullOrEmpty(optOutKey) || !Regex.IsMatch(optOutKey, @\"^[A-Za-z0-9._-]{1,127}$\"))\n                throw new ArgumentException($\"Key must be non-null, between 1 and 127 characters, and be a valid XML tag.\", nameof(optOutKey));\n        }\n\n        private static void ThrowIfMessageIsInvalid(string messageText)\n        {\n            if (string.IsNullOrWhiteSpace(messageText))\n                throw new ArgumentNullException(nameof(messageText), \"Dialog message text cannot be null or whitespace.\");\n        }\n\n        private static void ThrowIfButtonTextIsInvalid(string buttonText, string parameterName)\n        {\n            const int kMaxButtonTextLength = 64; // This limit is probably not necessary, but it's good to have a limit on the button text as well.\n            if (buttonText != null && buttonText.Length > kMaxButtonTextLength)\n                throw new ArgumentException($\"Text on buttons must be less than {kMaxButtonTextLength} characters long.\", parameterName);\n        }\n\n        /// <summary>\n        /// Displays a simple alert dialog box with a title, an icon, a message, and a single button.\n        /// </summary>","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/EditorDialog.cs#L184-L220","documentation":"Thrown by EditorDialog.ThrowIfOptOutKeyIsInvalid when the optOutKey is null/empty or fails the regex ^[A-Za-z0-9._-]{1,127}$ — i.e. it must be 1–127 characters of only alphanumerics, dot, underscore, or hyphen. The restriction exists because the key is used as an XML tag (Linux prefs), a Windows registry key name, and an NSPreference path, with the 'DialogOptOut.' prefix and a Unity registry prefix added on top.","triggerScenarios":"Calling an EditorDialog opt-out overload (the ones taking DialogOptOutDecisionType + storageKey) with a key containing spaces, slashes, non-ASCII, exceeding 127 chars, or null/empty.","commonSituations":"Using a human-readable phrase or a file path as the key; a key derived from a localized string with spaces/unicode; a key longer than 127 chars from concatenating identifiers.","solutions":["Use a short, stable, machine-style identifier (e.g. 'com.company.feature.confirm') as the key.","Strip/replace disallowed characters and truncate to <=127 chars before passing.","Validate with the same regex before calling."],"exampleFix":"// before\nEditorDialog.DisplayDialog(..., DialogOptOutDecisionType.ForThisSession, \"Delete asset? (y/n)\");\n// after\nEditorDialog.DisplayDialog(..., DialogOptOutDecisionType.ForThisSession, \"com.company.deleteAssetConfirm\");","handlingStrategy":"validation","validationCode":"static readonly Regex kKeyRe = new Regex(@\"^[A-Za-z0-9._-]{1,127}$\");\nstatic string SanitizeKey(string key)\n{\n    key = Regex.Replace(key ?? \"\", @\"[^A-Za-z0-9._-]\", \"_\");\n    return key.Length > 127 ? key.Substring(0, 127) : key;\n}","typeGuard":"static bool IsValidOptOutKey(string key) =>\n    !string.IsNullOrEmpty(key) && Regex.IsMatch(key, @\"^[A-Za-z0-9._-]{1,127}$\");","tryCatchPattern":null,"preventionTips":["Use stable dotted identifiers (com.company.feature) as opt-out keys.","Never use human-readable phrases, paths, or localized strings as keys.","Generate keys once and reuse; keep them under 64 chars for margin."],"tags":["editor","dialog","validation","regex","prefs","registry"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}