ppy/osu · error · InvalidOperationException

Color must be specified with 8-bit integer components

Error message

Color must be specified with 8-bit integer components

What it means

Thrown by LegacyDecoder.convertSettingStringToColor4 when the colour string has the correct number of components (3 or 4) but one or more components cannot be parsed as a byte (0–255 unsigned integer). The inner try/catch around byte.Parse catches any format or overflow exception and re-throws this message.

Source

Thrown at osu.Game/Beatmaps/Formats/LegacyDecoder.cs:120

            return line;
        }

        private Color4 convertSettingStringToColor4(string[] split, bool allowAlpha, KeyValuePair<string, string> pair)
        {
            if (split.Length != 3 && split.Length != 4)
                throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B or R,G,B,A): {pair.Value}");

            Color4 colour;

            try
            {
                byte alpha = allowAlpha && split.Length == 4 ? byte.Parse(split[3]) : (byte)255;
                colour = new Color4(byte.Parse(split[0]), byte.Parse(split[1]), byte.Parse(split[2]), alpha);
            }
            catch
            {
                throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
            }

            return colour;
        }

        protected void HandleColours<TModel>(TModel output, string line, bool allowAlpha)
        {
            var pair = SplitKeyVal(line);

            string[] split = pair.Value.Split(',');
            Color4 colour = convertSettingStringToColor4(split, allowAlpha, pair);

            bool isCombo = pair.Key.StartsWith(@"Combo", StringComparison.Ordinal)
                           && int.TryParse(pair.Key[5..], out int comboIndex)
                           && comboIndex >= 1 && comboIndex <= MAX_COMBO_COLOUR_COUNT;

            if (isCombo)
            {

View on GitHub (pinned to d9c73e12ad)

Solutions

  1. Inspect the colour line and ensure every component is an integer between 0 and 255 inclusive.
  2. Round or clamp any floating-point values: '255.5' → '255' or '256'.
  3. Clamp out-of-range values: '300' → '255', '-1' → '0'.
  4. Remove any non-numeric text from the colour fields.

Example fix

// before (.osu [Colours] section):
// Combo1 : 255,0,300
// Combo2 : 255.5,0,0

// after:
// Combo1 : 255,0,255
// Combo2 : 255,0,0
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate each colour component is a valid byte
string[] split = pair.Value.Split(',');
foreach (string s in split)
{
    if (!byte.TryParse(s, out _))
        throw new InvalidOperationException($"Colour component '{s}' is not a valid 8-bit integer");
}

Try / catch

try
{
    decoder.Decode(reader);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("8-bit integer components"))
{
    Logger.Log($"Colour value out of byte range in beatmap: {ex.Message}", LoggingTarget.Database);
}

Prevention

When it happens

Trigger: Decoding a .osu/.osb file where a colour line has the right number of values but at least one isn't a valid 8-bit unsigned integer — e.g. 'Combo1 : 255,0,300' (300 > 255), 'Combo1 : 255,0,red' (non-numeric), 'Combo1 : 255.5,0,0' (floating point), or 'Combo1 : -1,0,0' (negative).

Common situations: Manual editing with floating-point or out-of-range colour values; a skin editor that allows out-of-gamut colour values; decimal colour values from a conversion tool that weren't rounded to integers.

Related errors


AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13). Data as JSON: /api/errors/a216ed347ad356e3. Report an issue: GitHub.