This article relates to GRIB edition 2

You may wonder why you can do this:

% grib_set -s scaleFactorOfFirstFixedSurface=missing,scaledValueOfFirstFixedSurface=missing $IN $OUT

But not:

% grib_set -s typeOfFirstFixedSurface=missing $IN $OUT
ECCODES ERROR   :  unable to set typeOfFirstFixedSurface=missing (Value cannot be missing)

The answer lies in the difference between those keys. scaleFactorOfFirstFixedSurface and scaledValueOfFirstFixedSurface are integer keys with 1 and 4 bytes respectively. Their values can be any integer that will fit in that many bytes, for example scaledValueOfFirstFixedSurface can go from 0 to 4,294,967,295 (=2**32 - 1). Setting it to the maximum value will set all the bits to 1 which is the MISSING value (WMO Regulation 92.1.4). So when you use the keyword "missing" in the first command, ecCodes actually sets this value.

The other key typeOfFirstFixedSurface is a Code Table key whose values come from the entries in the Code Table 4.5. That table happens to have an entry (last one) of 255 which indicates a missing level however there are some code tables which do not have such an entry. For example Code table 4.234 and Code table 4.236. One could argue that the WMO should always include a missing entry in all their code tables but this is not the case. Even if they change this policy, previous versions of the GRIB2 tables will not have those 'missing' entries.

So the correct command is:

% grib_set -s typeOfFirstFixedSurface=255  $IN $OUT

Also see What are Code and Flag tables - ecCodes GRIB and BUFR FAQ