How would you find and fix every dead k6 module import in scripts written for k6 v0.5x?
answer
- read the paths, do not sed them
- six removed paths, four kinds of destination
- two of them want the import deleted
- one of them left the binary entirely
basics
~20 sScan the sources for k6/experimental/ rather than discovering the paths one failed run at a time, then classify each hit by hand. k6 v2's six removed paths lead to four different destinations, so a blanket rename is wrong for most of them.
solid answer
~40 sGrep the script tree for `k6/experimental/` first. A run only ever tells you about the first dead path it instantiates, so a fix-and-rerun loop costs one round trip per bad import, while a static scan finds all of them at once. Then classify each hit, because the six removed paths in k6 v2 go to four different kinds of destination: `browser` and `grpc` graduated to the core paths `k6/browser` and `k6/net/grpc`; `timers` and `webcrypto` became globals, so the correct edit is to **delete** the import; `tracing` moved out of the binary into a jslib module; and `redis` left core for the `k6/x/redis` extension, which a stock binary cannot resolve at all. Only `k6/experimental/websockets` still works, with a warning.
code
bash · 2 lines# find every path under the prefix in one pass, before running anything
grep -rn --include='*.js' -e 'k6/experimental/' ./testsgo deeper
Know that a dead k6 import stops the run and that the error names the replacement. Following that message one script at a time is a reasonable junior contribution.
Explain why the removed paths do not share one destination, and be able to say which two want the import deleted rather than renamed because the API became global.
Own the sweep: scan the sources instead of iterating on failed runs, classify every hit, separate the extension case from the text edits, and smoke-test the result.
Decide how a k6 major upgrade is sequenced across a shared script library, who owns the extension-backed cases, and whether experimental paths are inventoried before the next migration.
## Why you scan the source rather than run the scripts A removed module path in k6 v2 throws while the script is being loaded. That aborts the run at the first offending path, so a script with three dead imports needs three runs before it starts. Worse, the throw hides everything behind it: you cannot see the other two until the first is fixed. A static scan of the sources has neither problem. ```bash grep -rn --include='*.js' -e 'k6/experimental/' ./tests ``` Every hit is then classified by hand against the table below. **Do not sed.** ## The complete map of dead paths in k6 v2 | path in an old script | where it went | the edit | |---|---|---| | `k6/experimental/browser` | core module `k6/browser` | change the specifier | | `k6/experimental/grpc` | core module `k6/net/grpc` | change the specifier | | `k6/experimental/timers` | globals (`setTimeout`, `setInterval`, ...) | delete the import line | | `k6/experimental/webcrypto` | the global `crypto` object | delete the import line | | `k6/experimental/tracing` | a jslib module fetched over https | repoint at the jslib module | | `k6/experimental/redis` | the `k6/x/redis` extension | needs a binary that carries it | | `k6/experimental/websockets` | core module `k6/websockets` | still works today, warns | Four destinations, not one: a core path, no import at all, a remote library, and an extension. That is the whole reason the job cannot be automated with a regular expression. ## Why the mechanical rewrite is the classic failure The tempting fix is `s|k6/experimental/|k6/|` across the tree. Applied to the seven paths above it happens to land on a registered core path in exactly three cases -- `k6/browser`, `k6/timers` and `k6/websockets` -- and lands on a name k6 has never registered in the other four: `k6/grpc`, `k6/webcrypto`, `k6/tracing` and `k6/redis`. That trade is strictly bad. Before the rewrite, k6 threw an error that named the correct destination. After it, you get an unknown-modules error that lists the names k6 could not load and suggests you need extension resolution or a custom binary -- true in general, useless here, and it no longer tells you what the module became. You have destroyed the diagnostic. The `timers` case deserves its own note: the rewrite to `k6/timers` *works*, because `k6/timers` is a real core module. It is still not the intended migration. The functionality is global now, so the import buys nothing, and leaving it in place hides the fact that the script no longer needs it. ## The method, in order 1. **Scan**, don't run. Grep for `k6/experimental/` and collect every hit with its file and line. 2. **Classify** each hit against the table. Two of the seven want a deletion, not a rename. 3. **Deal with `redis` separately.** It is no longer in core at all, so it is not a text edit -- the path only resolves on a binary that carries the extension. Track it as its own task rather than letting it block the other six. 4. **Leave the deprecation for last.** `k6/experimental/websockets` does not fail anything today, so fix it deliberately rather than mixing it into an urgent migration; it is guaranteed for the rest of the v2 line. 5. **Smoke each converted script** with a single iteration. The load either aborts, naming a path you missed, or gets far enough to execute. Expect at most one new name per run. ## What the scan will not catch Two blind spots are worth stating: - **Import paths built at run time.** A specifier assembled from a variable is invisible to grep. These are rare in k6 suites, but if your repository has a helper that composes module names, read it rather than trusting the scan. - **Paths that are current but experimental.** `k6/experimental/csv`, `k6/experimental/fs` and `k6/experimental/streams` will show up in the same grep and are perfectly fine to keep. Note them anyway: they are the paths that may move next, and having the list is most of the work when they do. ## The one hit that is not a text edit `k6/experimental/redis` is the odd one out and deserves separating from the sweep early. The other five removed paths are satisfied by editing or deleting a line, because their functionality is still inside the k6 binary or, for tracing, in a library your script can fetch. Redis is not: it left core for the `k6/x/` namespace, which is where k6 registers extension modules and which a stock binary does not resolve at all. The visible difference is the error. The old path throws a migration message naming `k6/x/redis`; the new path, on a plain binary, produces an unknown-modules error instead. Both are accurate -- the module exists, just not in the binary you are running. Track it as its own item so it does not block the six edits that are genuinely edits. Done properly this is a one-pass job. Done as a fix-and-rerun loop against a suite of a hundred scripts, it is an afternoon.
- Which blanket renames of k6/experimental/X to k6/X actually work in k6 v2?Only three: `browser`, `timers` and `websockets` land on registered core paths. `grpc` becomes `k6/grpc`, and `webcrypto`, `tracing` and `redis` likewise land on names k6 has never registered, so you trade a clear migration message for an unknown-modules error.
- What error does k6 v2 give for an import name it does not recognise at all?An unknown-modules error that lists the names it could not load and says extension resolution or a custom k6 binary is likely needed. It is a different error from the migration message a removed core path throws, and it means k6 has no record of the name.
- How do you confirm a converted k6 script before trusting it?Run it once with a single iteration. A removed path aborts the load, so the run either dies immediately naming the offending path or gets far enough to execute the default function. Repeat, because only one dead import surfaces per run.
saying these in an interview costs you the question
- Runs a blanket rename of k6/experimental/ to k6/
- Assumes every graduated module kept its trailing path segment
- Expects one k6 run to report all the dead imports at once
- Thinks k6/x/redis resolves in the stock k6 binary
- Treats the surviving deprecation warning as nothing to act on