{"record":{"id":"f73f8b448ea11452","repo":"microsoft/typescript-go","slug":"expected-version-in-custom-gcl-yml","errorCode":null,"errorMessage":"Expected version in .custom-gcl.yml","messagePattern":"Expected version in \\.custom-gcl\\.yml","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Herebyfile.mjs","lineNumber":852,"sourceCode":"    dependencies: [tsgo, buildAPITests],\r\n    run: async () => {\r\n        // Prevent interleaving by running these directly instead of in parallel.\r\n        await runTests();\r\n        await runTestBenchmarks();\r\n        await runTestTools();\r\n        await runTestAPI();\r\n    },\r\n});\r\n\r\nconst customLinterPath = \"./_tools/custom-gcl\";\r\nconst customLinterHashPath = customLinterPath + \".hash\";\r\n\r\nconst golangciLintPackage = memoize(() => {\r\n    const golangciLintYml = fs.readFileSync(\".custom-gcl.yml\", \"utf8\");\r\n    const pattern = /^version:\\s*(v\\d+\\.\\d+\\.\\d+).*$/m;\r\n    const match = pattern.exec(golangciLintYml);\r\n    if (!match) {\r\n        throw new Error(\"Expected version in .custom-gcl.yml\");\r\n    }\r\n    const version = match[1];\r\n    const major = version.split(\".\")[0];\r\n    const versionSuffix = [\"v0\", \"v1\"].includes(major) ? \"\" : \"/\" + major;\r\n\r\n    return `github.com/golangci/golangci-lint${versionSuffix}/cmd/golangci-lint@${version}`;\r\n});\r\n\r\nconst customlintHash = memoize(() => {\r\n    const files = glob.sync([\r\n        \"./_tools/go.mod\",\r\n        \"./_tools/customlint/**/*\",\r\n        \"./.custom-gcl.yml\",\r\n    ], {\r\n        ignore: \"**/testdata/**\",\r\n        nodir: true,\r\n        absolute: true,\r\n    });\r","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/microsoft/typescript-go/blob/1bcfa18d79a3be41772223d5c05dfe4480e614ff/Herebyfile.mjs#L834-L870","documentation":"After the trace file is closed and the legend successfully marshaled, StopTracing writes legend.json into traceDir via fs.WriteFile. This error means that final write failed — the trace events and types dumps may exist, but the legend that maps them is missing, so downstream tooling cannot correlate checkers with their type files. It is the legend-side counterpart of the header-write error at startup.","triggerScenarios":"StopTracing when traceDir or legend.json is not writable: directory deleted mid-session, read-only mount at teardown, permission change, disk full at the final write, or legend.json existing as a directory.","commonSituations":"Trace output directory removed or locked by cleanup jobs while the process was still running; disk exhaustion right at exit; containers unmounting volumes before graceful shutdown completes; running as a different user than the one that created traceDir.","solutions":["Re-run with a writable, existing traceDir (os.MkdirAll it first and confirm ownership/permissions).","Free disk space — legend.json is tiny but the write still fails on a full volume.","Keep the trace directory untouched for the whole process lifetime; schedule cleanup only after the process exits.","If legend.json is a directory or root-owned file from an earlier run, remove it before tracing."],"exampleFix":"// before\ntr, _ := tracing.StartTracing(fs, traceDir, cfg, false)\ndefer tr.StopTracing()\n\n// after: guarantee writable teardown\nif err := os.MkdirAll(traceDir, 0o755); err != nil { return err }\ntr, err := tracing.StartTracing(fs, traceDir, cfg, false)\nif err != nil { return err }\ndefer func() { _ = tr.StopTracing() }()","handlingStrategy":"validation","validationCode":"// ensure legend.json is writable at teardown as well\ninfo, err := os.Stat(traceDir)\nif err != nil || !info.IsDir() || info.Mode().Perm()&0o200 == 0 {\n\treturn fmt.Errorf(\"trace dir missing or read-only: %s\", traceDir)\n}","typeGuard":null,"tryCatchPattern":"if err := tr.StopTracing(); err != nil {\n\tif strings.Contains(err.Error(), \"failed to write legend file\") {\n\t\t// trace.json and types_*.json may exist; legend mapping is lost — re-run to get a complete set\n\t\tlog.Printf(\"legend missing, trace incomplete set: %v\", err)\n\t}\n}","preventionTips":["Create traceDir with MkdirAll and stable ownership before the session.","Don't clean the trace directory while tsgo is running.","Treat legend.json, trace.json and types_*.json as one atomic set; if any write failed, re-run tracing."],"tags":["tracing","filesystem","io","teardown"],"backgroundTag":null,"analyzedSha":"1bcfa18d79a3be41772223d5c05dfe4480e614ff","analyzedAt":"2026-08-16T02:12:00.115Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}