{"record":{"id":"a8659a188d8874d9","repo":"SixLabors/ImageSharp","slug":"input-string-length-must-be-a-multiple-of-2","errorCode":null,"errorMessage":"Input string length must be a multiple of 2","messagePattern":"Input string length must be a multiple of 2","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Common/Helpers/HexConverter.cs","lineNumber":21,"sourceCode":"\nusing System.Runtime.CompilerServices;\n\nnamespace SixLabors.ImageSharp.Common.Helpers;\n\ninternal static class HexConverter\n{\n    /// <summary>\n    /// Parses a hexadecimal string into a byte array without allocations. Throws on non-hexadecimal character.\n    /// Adapted from https://source.dot.net/#System.Private.CoreLib/Convert.cs,c9e4fbeaca708991.\n    /// </summary>\n    /// <param name=\"chars\">The hexadecimal string to parse.</param>\n    /// <param name=\"bytes\">The destination for the parsed bytes. Must be at least <paramref name=\"chars\"/>.Length / 2 bytes long.</param>\n    /// <returns>The number of bytes written to <paramref name=\"bytes\"/>.</returns>\n    public static int HexStringToBytes(ReadOnlySpan<char> chars, Span<byte> bytes)\n    {\n        if (Numerics.Modulo2(chars.Length) != 0)\n        {\n            throw new ArgumentException(\"Input string length must be a multiple of 2\", nameof(chars));\n        }\n\n        if ((bytes.Length << 1 /* bit-hack for *2 */) < chars.Length)\n        {\n            throw new ArgumentException(\"Output span must be at least half the length of the input string\");\n        }\n\n        // Slightly better performance in the loop below, allows us to skip a bounds check\n        // while still supporting output buffers that are larger than necessary\n        bytes = bytes[..(chars.Length >> 1)];   // bit-hack for / 2\n\n        [MethodImpl(MethodImplOptions.AggressiveInlining)]\n        static int FromChar(int c)\n        {\n            // Map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.\n            // This doesn't actually allocate.\n            ReadOnlySpan<byte> charToHexLookup =\n            [","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Common/Helpers/HexConverter.cs#L3-L39","documentation":"HexConverter.HexStringToBytes parses a hex string into bytes and requires the character span length to be even, since every output byte consumes exactly two hex characters. An odd-length input cannot be parsed unambiguously, so an ArgumentException naming the 'chars' parameter is thrown.","triggerScenarios":"Calling HexStringToBytes with a ReadOnlySpan<char> whose Length is odd, e.g. \"ABC\" or a truncated hex literal produced by string slicing.","commonSituations":"Hand-copied hex color/identifier strings with a dropped digit; parsing concatenated hex tokens where one is truncated; off-by-one substring offsets.","solutions":["Validate/normalize the hex string to an even length before calling (pad a leading 0 or reject the input).","Fix the slicing logic that produced the odd-length span.","Catch ArgumentException and report a user-facing invalid-hex-format error."],"exampleFix":"// before\nHexConverter.HexStringToBytes(\"A1B2C\".AsSpan(), dest);\n// after\nvar hex = \"A1B2C\";\nif (hex.Length % 2 != 0) hex = \"0\" + hex; // or throw InvalidDataException\nHexConverter.HexStringToBytes(hex.AsSpan(), dest);","handlingStrategy":"validation","validationCode":"if (hex.Length == 0 || hex.Length % 2 != 0)\n    throw new FormatException($\"Hex string must have an even length, got {hex.Length}.\");","typeGuard":"static bool IsEvenLengthHex(ReadOnlySpan<char> s) => s.Length % 2 == 0;","tryCatchPattern":"try { written = HexConverter.HexStringToBytes(hex.AsSpan(), dest); }\ncatch (ArgumentException ex) { throw new FormatException(\"Invalid hex string length.\", ex); }","preventionTips":["Validate even length and hex charset before calling.","Fix string-slicing boundaries that can chop a hex pair.","Prefer Convert.FromHexString for untrusted user input to get clearer errors."],"tags":["hex","argument-exception","parsing","helpers"],"backgroundTag":"invalid-argument-format","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}