{"record":{"id":"7d392fa7f1fda1ae","repo":"SubtitleEdit/subtitleedit","slug":"vobsub-idx-input-has-no-companion-sub-path","errorCode":null,"errorMessage":"VobSub '.idx' input has no companion '.sub' ({Path.GetFileName(subPath)}) — the .idx only holds timing and palette; the subtitle images live in the .sub.","messagePattern":"VobSub '\\.idx' input has no companion '\\.sub' \\((.+?)\\) — the \\.idx only holds timing and palette; the subtitle images live in the \\.sub\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/ContainerSubtitleLoader.cs","lineNumber":112,"sourceCode":"            {\n                AnsiConsole.MarkupLine(\n                    $\"[yellow]Note: VobSub '.sub' has no '.idx' companion ({Path.GetFileName(idxPath).EscapeMarkup()}); \"\n                    + \"reading timing from the stream and using a default color palette.[/]\");\n                return LoadVobSub(filePath, idxPath, options);\n            }\n\n            return null;\n        }\n\n        if (ext == \".idx\")\n        {\n            // 5.0.0 accepted the .idx of a VobSub pair as the input file; keep that working\n            // by redirecting to the companion .sub (which holds the actual subpictures) and\n            // using the given .idx for timing + palette (issue #12772).\n            var subPath = Path.ChangeExtension(filePath, \".sub\");\n            if (!File.Exists(subPath))\n            {\n                throw new InvalidOperationException(\n                    $\"VobSub '.idx' input has no companion '.sub' ({Path.GetFileName(subPath)}) — \"\n                    + \"the .idx only holds timing and palette; the subtitle images live in the .sub.\");\n            }\n\n            return LoadVobSub(subPath, filePath, options);\n        }\n\n        if (ext is \".ts\" or \".m2ts\" or \".mts\")\n        {\n            return LoadTransportStream(filePath, options);\n        }\n\n        if (ext == \".mxf\")\n        {\n            return LoadMxf(filePath, options);\n        }\n\n        return null;","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/ContainerSubtitleLoader.cs#L94-L130","documentation":"Thrown by ContainerSubtitleLoader when the input file has a .idx extension but no companion .sub exists beside it (Path.ChangeExtension to .sub yields a non-existent file). A VobSub .idx only holds timing and palette metadata; the actual subtitle images live in the .sub, so the conversion cannot proceed without it. The redirect from .idx to .sub preserves the 5.0.0 behaviour documented against issue #12772.","triggerScenarios":"Invoking TryLoadTracks(filePath, options) (or the CLI) with a path ending in .idx where the sibling .sub (same basename, same directory) is absent — File.Exists(subPath) at line 110 returns false.","commonSituations":"User selects only the .idx of a VobSub pair; the .sub was deleted or never copied alongside; case-sensitivity on Linux where the file is .SUB but ChangeExtension produces .sub; pointing the tool at a lone .idx downloaded without its pair.","solutions":["Locate the matching .sub file and place it next to the .idx with the same basename.","Pass the .sub path directly instead of the .idx (the loader pairs them automatically when both exist).","On case-sensitive filesystems, ensure the .sub extension matches exactly, or rename to lowercase .sub."],"exampleFix":"// before: only movie.idx present\nseconv movie.idx -o out.srt\n\n// after: provide the companion .sub\nseconv movie.sub -o out.srt   # .idx is auto-detected beside it","handlingStrategy":"validation","validationCode":"// Validate the .idx/.sub pair exists before invoking the loader.\nif (Path.GetExtension(filePath).Equals(\".idx\", StringComparison.OrdinalIgnoreCase))\n{\n    var subPath = Path.ChangeExtension(filePath, \".sub\");\n    if (!File.Exists(subPath))\n        return Error($\"Missing companion .sub next to {filePath}\");\n}","typeGuard":null,"tryCatchPattern":"try { return ContainerSubtitleLoader.TryLoadTracks(filePath, options); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"companion '.sub\"))\n{ Console.Error.WriteLine(ex.Message); return null; }","preventionTips":["Before converting, confirm both the .idx and .sub of a VobSub pair exist in the same directory.","Pass the .sub as input rather than the .idx to make the dependency explicit.","On case-sensitive filesystems, keep extensions lowercase (.sub) to match Path.ChangeExtension output."],"tags":["vobsub","idx","sub","file-not-found","subtitle"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}