{"record":{"id":"e0d8c53e6e0073c8","repo":"grafana/k6","slug":"error-while-parsing-use-directives-in-q-w","errorCode":null,"errorMessage":"error while parsing use directives in %q: %w","messagePattern":"error while parsing use directives in %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/launcher.go","lineNumber":412,"sourceCode":"\t\tdirective = strings.TrimSpace(strings.TrimPrefix(directive, \"use k6\"))\n\t\tdep := \"k6\"\n\t\tconstraint := directive\n\t\tif strings.HasPrefix(directive, \"with k6/x/\") {\n\t\t\tdirective = strings.TrimSpace(strings.TrimPrefix(directive, \"with \"))\n\t\t\tdep, constraint, _ = strings.Cut(directive, \" \")\n\t\t}\n\t\tvar con *semver.Constraints\n\t\tvar err error\n\t\tif len(constraint) > 0 {\n\t\t\tcon, err = semver.NewConstraint(constraint)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error while parsing use directives constraint %q for %q in %q: %w\", constraint, dep, name, err)\n\t\t\t}\n\t\t}\n\n\t\terr = deps.update(dep, con)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error while parsing use directives in %q: %w\", name, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc findDirectives(text []byte) []string {\n\t// parse #! at beginning of file\n\tif bytes.HasPrefix(text, []byte(\"#!\")) {\n\t\t_, text, _ = bytes.Cut(text, []byte(\"\\n\"))\n\t}\n\n\tvar result []string\n\n\tfor i := 0; i < len(text); {\n\t\tr, width := utf8.DecodeRune(text[i:])\n\t\tswitch {\n\t\tcase unicode.IsSpace(r) || r == rune(';'): // skip all spaces and ;","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/cmd/launcher.go#L394-L430","documentation":"Emitted right after constraint parsing while processing `use` directives: the parsed dependency/constraint pair is merged into the dependency set with deps.update, which errors with 'already have constraint for %q, when parsing %q' when a second, different constraint arrives for a dependency that already has a non-star constraint. Only the first meaningful constraint for a dependency is kept; a conflicting second one is rejected.","triggerScenarios":"Two `use k6` directives with different constraints in one file (`use k6 >= v0.50` then `use k6 < v0.50`), or constraints spread across files: the main script pins `use k6 v0.56.0` while an imported helper's header says `use k6 v0.55.0`; the same applies to extensions like k6/x/foo constrained differently in two places. Repeating the identical constraint, or going from an unconstrained/star constraint to a specific one, is allowed.","commonSituations":"Shared helper modules copied between projects that carry their own `use` headers; bumping the version in the entry script but not in imported local files; a dependency manifest (K6_DEPENDENCIES) interacting with directives — the manifest fills only unconstrained entries, then a conflicting directive arrives.","solutions":["Locate every `use` directive across the entry script and all local imports: `grep -rn \"^use \" .`","Make the constraints identical for the conflicting dependency, or remove the duplicate from the less authoritative file","If files legitimately need different versions, align them to one range (e.g. both `>= v0.56.0`)","Re-run k6; only the first conflict is reported at a time, so repeat until clean"],"exampleFix":"// before\n// main.js: use k6 >= v0.56.0\n// lib/helpers.js: use k6 v0.55.0\n// error: error while parsing use directives in \"lib/helpers.js\": already have constraint for \"k6\", ...\n\n// after\n// lib/helpers.js: use k6 >= v0.56.0","handlingStrategy":"validation","validationCode":"# Detect duplicate/conflicting use directives across entry + local imports before running\ngrep -rhoE '^use k6( with [^ ]+)? .*' --include='*.js' . | sort | uniq -d\n# any output means the same dependency is constrained more than once — align them","typeGuard":"function conflictingDeps(directivesPerFile) {\n  const seen = new Map();\n  for (const [file, lines] of Object.entries(directivesPerFile)) {\n    for (const l of lines) {\n      const m = l.match(/^use\\s+k6\\s+(.*)$/); if (!m) continue;\n      if (seen.has(m[1]) && seen.get(m[1]).file !== file) return { conflict: m[1], files: [seen.get(m[1]).file, file] };\n      seen.set(m[1], { file });\n    }\n  }\n  return null;\n}","tryCatchPattern":null,"preventionTips":["Put the `use k6` directive only in the entry script, not in shared helpers","When copying helper modules between projects, strip their use headers","Keep K6_DEPENDENCIES consistent with directives — it only fills unconstrained deps"],"tags":["semver","directives","dependencies","imports"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}