{"record":{"id":"22ab3a9f47a129a6","repo":"dotnet/wpf","slug":"sr-faceindexvalidonlyforttc","errorCode":null,"errorMessage":"SR.FaceIndexValidOnlyForTTC","messagePattern":"SR\\.FaceIndexValidOnlyForTTC","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontFace/FontDriver.cs","lineNumber":158,"sourceCode":"            }\n            catch (ArgumentOutOfRangeException e)\n            {\n                // convert exceptions from CheckedPointer to FileFormatException\n                throw new FileFormatException(SourceUri, e);\n            }\n        }\n\n        internal void SetFace(int faceIndex)\n        {\n            if (_technology == FontTechnology.TrueTypeCollection)\n            {\n                ArgumentOutOfRangeException.ThrowIfNegative(faceIndex);\n                ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(faceIndex, _numFaces);\n            }\n            else\n            {\n                if (faceIndex != 0)\n                    throw new ArgumentOutOfRangeException(nameof(faceIndex), SR.FaceIndexValidOnlyForTTC);\n            }\n\n            try\n            {\n                CheckedPointer seekPosition = _fileStream + 4;\n\n                if (_technology == FontTechnology.TrueTypeCollection)\n                {\n                    // this is a TTC file, we need to decode the ttc header\n\n                    // skip version, num faces, OffsetTable array\n                    seekPosition += (4 + 4 + 4 * faceIndex);\n\n                    _directoryOffset = ReadOpenTypeLong(seekPosition);\n\n                    seekPosition = _fileStream + (_directoryOffset + 4);\n                    // 4 means that we skip the version number\n                }","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontFace/FontDriver.cs#L140-L176","documentation":"SetFace allows switching faces only for TrueType Collection (.ttc) files. For single-face fonts (plain TTF/OTF), the only valid index is 0; any other index throws ArgumentOutOfRangeException with SR.FaceIndexValidOnlyForTTC.","triggerScenarios":"Calling SetFace(faceIndex) (directly or via ComputeSubset) on a TrueTypeFontDriver whose _technology is not TrueTypeCollection while faceIndex != 0.","commonSituations":"Subsetting or enumerating faces of a plain .ttf as if it were a .ttc, loop code that indexes faces without checking the font technology, tooling that assumes all font files contain multiple faces.","solutions":["Check the driver's font technology and only pass non-zero face indexes to .ttc files","For single-face fonts always call SetFace(0) or skip the call","Clamp/normalize the requested index: faceIndex = isCollection ? faceIndex : 0"],"exampleFix":"// before\ndriver.SetFace(requestedIndex); // crashes for .ttf with index 2\n// after\nif (driver.Technology == FontTechnology.TrueTypeCollection)\n    driver.SetFace(requestedIndex);\nelse\n    driver.SetFace(0);","handlingStrategy":"validation","validationCode":"if (!isCollection && faceIndex != 0)\n    throw new ArgumentException(\"faceIndex must be 0 for non-TTC fonts\");","typeGuard":null,"tryCatchPattern":"try { driver.SetFace(faceIndex); }\ncatch (ArgumentOutOfRangeException)\n{\n    driver.SetFace(0); // single-face fallback\n}","preventionTips":["Check the font technology before indexing faces","Treat plain .ttf/.otf files as single-face (index 0) always","Enumerate faces only after confirming TrueTypeCollection format"],"tags":["wpf","fonts","truetype-collection","argument-out-of-range"],"backgroundTag":"argument-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}