{"record":{"id":"9c8d27da38538a35","repo":"stride3d/stride","slug":"solution-filter-filterfile-does-not-reference-a-solution","errorCode":null,"errorMessage":"Solution filter '{filterFile}' does not reference a solution.","messagePattern":"Solution filter '(.+?)' does not reference a solution\\.","errorType":"exception","errorClass":"SolutionFileException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.Design/Solutions/SolutionSerialization.cs","lineNumber":49,"sourceCode":"            ?? throw new SolutionFileException($\"Unsupported solution file format: '{solutionFullPath}'.\");\n        var model = serializer.OpenAsync(solutionFullPath, CancellationToken.None).GetAwaiter().GetResult();\n        var solution = ToSolution(model, solutionFullPath);\n        ReadDefaultStartup(solution, solutionFullPath);\n        return solution;\n    }\n\n    // The .sln a solution filter (.slnf) points at, resolved relative to the filter file.\n    private static string ResolveSolutionFilterTarget(string filterFile)\n    {\n        using var document = JsonDocument.Parse(File.ReadAllText(filterFile));\n        if (document.RootElement.TryGetProperty(\"solution\", out var solution)\n            && solution.TryGetProperty(\"path\", out var path)\n            && path.GetString() is { } relativePath)\n        {\n            return Path.GetFullPath(Path.Combine(Path.GetDirectoryName(filterFile)!, relativePath.Replace('\\\\', Path.DirectorySeparatorChar)));\n        }\n\n        throw new SolutionFileException($\"Solution filter '{filterFile}' does not reference a solution.\");\n    }\n\n    public static Solution Read(string solutionFullPath, Stream stream)\n    {\n        var model = SolutionSerializers.SlnFileV12.OpenAsync(stream, CancellationToken.None).GetAwaiter().GetResult();\n        return ToSolution(model, solutionFullPath);\n    }\n\n    public static void Write(Solution solution, string outputPath, Action<string>? onBeforeOverwrite = null)\n    {\n        // Behave like Visual Studio: a solution loaded from disk keeps everything it had (platforms, build\n        // configurations, solution folders, projects Stride doesn't manage) and only its project list is\n        // reconciled. A solution that wasn't loaded from disk is created from a fresh model with defaults.\n        var model = solution.SourceModel is { } source ? new SolutionModel(source) : NewModel(solution);\n        Reconcile(model, solution, outputPath);\n\n        // Pick the serializer from the output extension so a .slnx round-trips as XML and a .sln as classic format.\n        var serializer = SolutionSerializers.GetSerializerByMoniker(outputPath) ?? SolutionSerializers.SlnFileV12;","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.Design/Solutions/SolutionSerialization.cs#L31-L67","documentation":"Thrown by ResolveSolutionFilterTarget when a .slnf solution-filter file parses as JSON but lacks the expected 'solution.path' property. A .slnf must point at a real .sln via solution.path for the library to open the underlying writable solution.","triggerScenarios":"Calling Read with a .slnf file whose JSON root object is missing the 'solution' property or whose 'solution.path' string is absent/null — e.g. a hand-edited or corrupted filter file.","commonSituations":"Manually authored .slnf with wrong schema, filter files saved by tools with different casing, truncated/corrupted JSON filters.","solutions":["Open the .slnf in an editor and ensure it contains a top-level \"solution\": { \"path\": \"...\" } property","Point 'path' at the correct .sln relative to the .slnf file's directory","Regenerate the solution filter in Visual Studio/IDE instead of hand-editing"],"exampleFix":"// before (broken .slnf)\n{ \"projects\": [\"src\\\\App\\\\App.csproj\"] }\n// after\n{ \"solution\": { \"path\": \"MyApp.sln\" }, \"projects\": [\"src\\\\App\\\\App.csproj\"] }","handlingStrategy":"validation","validationCode":"using var doc = JsonDocument.Parse(File.ReadAllText(filterPath));\nif (!doc.RootElement.TryGetProperty(\"solution\", out var s) ||\n    !s.TryGetProperty(\"path\", out _))\n    throw new InvalidDataException($\"{filterPath} has no solution.path\");","typeGuard":"bool IsValidFilter(string json) =>\n    JsonDocument.Parse(json).RootElement.TryGetProperty(\"solution\", out var s) &&\n    s.TryGetProperty(\"path\", out var p) && p.ValueKind == JsonValueKind.String;","tryCatchPattern":"try { return SolutionSerialization.Read(filterPath); }\ncatch (SolutionFileException ex) when (ex.Message.Contains(\"does not reference a solution\"))\n{\n    throw new InvalidDataException($\"Filter '{filterPath}' is missing 'solution.path'\", ex);\n}","preventionTips":["Never hand-edit .slnf files; regenerate them in the IDE","Validate the .slnf JSON schema before loading","Ensure the referenced .sln path resolves relative to the filter file"],"tags":["solution-filter","schema-validation","json"],"backgroundTag":"schema-validation-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}