Debugging Components
Debugging WebAssembly components is different from debugging native applications. You can't attach a traditional debugger to a Wasm component, and error messages from the build toolchain can be cryptic if you're not familiar with the Component Model. This page covers the diagnostic tools available to you, common errors you'll encounter, and how to resolve them.
Claude Code users can install skills that give Claude specialized information on WebAssembly component debugging. See the Useful WebAssembly Tools page for installation instructions for the webassembly-component-development and wash skills.
Diagnostic tools
wash inspect
Use wash inspect to view a compiled component's WIT world — its imports and exports:
wash inspect my_component.wasmThis shows you exactly which interfaces the component declares. If a component isn't behaving as expected at runtime, you can use wash inspect to confirm whether the component was built with the right interfaces.
You can also use wasm-tools component wit for the same purpose:
wasm-tools component wit ./build/output.wasmwasm-tools validate
Validate that a .wasm binary is a well-formed component:
wasm-tools validate ./build/output.wasmIf this fails, the binary isn't a valid Component Model component. This can happen when your build produces a core Wasm module instead of a component (for example, using a wrong compiler target).
Verbose build output
When wash build or wash dev fails with an unclear error, add --verbose or --log-level debug for detailed output:
wash build --verbose
wash build --log-level debugThe verbose output shows each step of the build pipeline — WIT dependency fetching, binding generation, compilation, and component encoding — so you can identify where the failure occurs.
Common build errors
WIT dependency errors
Symptom:
error: failed to read path for WIT [./wit]
Caused by:
No such file or directory (os error 2)
Cause: Your WIT files aren't at the expected path.
Fix: Ensure your wit/ directory exists and contains a world.wit file. If you're starting a new project, run wkg wit fetch (or wash wit fetch) to populate wit/deps/ with your interface dependencies.
Version mismatches
Symptom (Rust):
failed to find export of interface `wasi:http/incoming-handler@0.2.2` function `handle`
Symptom (TinyGo / TypeScript): Build errors mentioning a WASI interface version that doesn't match your WIT world.
Cause: The wasi:http/incoming-handler version in your wit/world.wit doesn't match the version your toolchain provides.
Fix: Check the version alignment for your language:
- Rust: Run
cargo tree -p wasip2and match the WASI HTTP version in your WIT world. See the Rust Language Guide: Version alignment for the version table. - TinyGo: Ensure the
wasi:httpversion in your WIT world matches whatwit-bindgen-goand TinyGo expect. See the Go Language Guide. - TypeScript: Match the version to your
jco/componentize-jsversion. See the TypeScript Language Guide.
After updating your WIT world, re-fetch dependencies:
rm -rf wit/deps wkg.lock && wkg wit fetchMissing function exports
Symptom:
error: failed to encode a component from module
Caused by:
0: failed to decode world from module
1: module was not valid
2: failed to find export of interface `wasmcloud:wash/plugin@0.0.1` function `info`
Cause: Your code doesn't export all functions required by your WIT world.
Fix: Check your WIT world definition and ensure your code implements every exported interface. For example, if your world exports wasi:http/incoming-handler, your code must provide a handler function for incoming HTTP requests.
Missing import resolution
Symptom:
error: failed to encode a component from module
Caused by:
0: failed to decode world from module
1: module was not valid
2: failed to resolve import `wasi:http/outgoing-handler@0.2.0::handle`
3: module requires an import interface named `wasi:http/outgoing-handler@0.2.0`
Cause: Your code uses an import that isn't declared in your WIT world, or bindings weren't generated correctly.
Fix:
- Add the import to your
wit/world.wit. - Re-fetch dependencies:
wkg wit fetch - Regenerate bindings (for Go:
go generate ./...; for TypeScript:jco types wit/ -o generated/types) - Rebuild.
Target and toolchain errors
Symptom (Rust):
error[E0463]: can't find crate for `std`
Cause: Building without the Wasm target.
Fix: Install and specify the target:
rustup target add wasm32-wasip2
cargo build --target wasm32-wasip2Symptom (TinyGo): Build errors referencing WIT world or package names.
Cause: The -wit-package or -wit-world flags in your Makefile don't match your wit/world.wit.
Fix: Ensure the -wit-world flag in your Makefile matches the world name in wit/world.wit, and -wit-package points to the correct WIT directory. See the Go Language Guide for the recommended Makefile setup.
Runtime errors
"Unknown import" errors
Symptom:
component imports instance `wasi:http/types@0.2.0`, but a matching implementation was not found in the linker
Cause: The runtime doesn't implement an interface your component imports. This happens when you use an import that the host runtime hasn't wired up.
Fix:
- Check that the runtime you're using supports the interface. For
wash dev, supported interfaces includewasi:http,wasi:cli,wasi:io,wasi:clocks,wasi:random, and others. - If you're using a draft or experimental interface (like
wasi:keyvalueorwasi:config), ensure your runtime is configured to provide it. - Use
wash inspectto verify which interfaces your component imports, then check your runtime's documentation for supported interfaces.
Threading errors
Symptom:
operation not supported on this platform
Or panics related to std::thread, std::sync::Mutex, or similar concurrency primitives.
Cause: WASI 0.2 does not support threads. Standard library threading APIs (std::thread in Rust, goroutines with shared state in Go) may compile but fail at runtime.
Fix:
- Rust: Use
wstd's async runtime instead ofstd::thread. Mainstream async runtimes (tokio,async-std) don't support WASI 0.2 yet. - Go: TinyGo supports goroutines via the
asyncifyscheduler, but some synchronization patterns may not work. Test concurrent code in the Wasm target specifically. - TypeScript: JavaScript is single-threaded by nature, so this is less likely to be an issue.
Unexpected behavior from stdlib modules
Some standard library modules compile to the wasip2 target but don't behave as expected:
net/httpin Go — does not work directly. Usewasihttp.HandleFuncandwasihttp.Transportfromgo.wasmcloud.dev/component.osin Go — limited; filesystem and process operations require WASI filesystem configuration.std::netandstd::fsin Rust — require OS-level syscalls not available in the Wasm sandbox. Usewstd::netand WASI filesystem interfaces.- Node.js APIs in TypeScript —
fs,path,os,child_process,Buffer,process.env,require()are not available. Use Web Standards APIs and WASI interfaces instead.
For a complete list of what works and what doesn't, see the compatibility sections of each language guide:
Language-specific debugging
Rust
Check compilation before building:
cargo check --target wasm32-wasip2This is faster than a full build and catches most type errors and missing imports.
Type conflicts with wit-bindgen:
If you use both wstd and wit-bindgen for custom WASI interfaces, you may get type conflicts when an interface shares types with wasi:io or other standard interfaces. Use wit-bindgen's with option to point to wasip2's types:
wit_bindgen::generate!({
world: "my-world",
path: "wit",
with: {
"wasi:io/streams@0.2.9": wasip2::wasi::io::streams,
"wasi:io/poll@0.2.9": wasip2::wasi::io::poll,
},
generate_all,
});See the Rust Language Guide: Handling type conflicts for details.
Go (TinyGo)
World not found — defaults to CLI. If TinyGo can't find the specified world, it silently targets wasi:cli/run instead of your intended world. Use wash inspect to check:
wash inspect ./build/output.wasmIf you see wasi:cli imports and export wasi:cli/run@0.2.0 instead of your expected world, verify:
- The
-wit-worldflag in your Makefile matches the world name inwit/world.wit. - The
-wit-packageflag points to the correct WIT directory (typically./wit). - Your WIT files are at the expected path.
Common TinyGo build errors are cataloged in the FAQ: Common issues with TinyGo builds.
TypeScript
@ts-expect-error for WASI imports. When importing WASI interfaces directly (rather than using the fetch event pattern), TypeScript may not resolve the import specifiers. Use @ts-expect-error or configure paths in your tsconfig.json:
{
"compilerOptions": {
"paths": {
"wasi:http/types@0.2.3": ["./generated/types/interfaces/wasi-http-types.d.ts"]
}
}
}bigint pitfalls. WASI interfaces use 64-bit integers, which map to JavaScript's bigint type. Watch for implicit number-to-bigint conversion issues and use BigInt() explicitly when needed.
StarlingMonkey limitations. TypeScript components run inside the StarlingMonkey engine (SpiderMonkey compiled to Wasm). Not all JavaScript APIs are available — notably, WebSocket support is missing, require() doesn't work (ESM only), and Buffer should be replaced with Uint8Array. See the TypeScript Language Guide: Library compatibility for details.
Logging
Adding log output to your component is one of the most effective debugging techniques.
Rust
Use the wasi:logging interface. The wstd crate doesn't include logging directly, but you can add it via wit-bindgen. For simple debugging, eprintln! writes to stderr and is visible in wash dev output.
Go (TinyGo)
Use the wasilog package from the wasmCloud Go component library:
import "go.wasmcloud.dev/component/log/wasilog"
func handleRequest(w http.ResponseWriter, r *http.Request) {
logger := wasilog.ContextLogger("handler")
logger.Info("request received", "path", r.URL.Path)
}TypeScript
Use console.log and console.error — StarlingMonkey routes these to WASI stderr:
console.log('Request received:', req.url);
console.error('Something went wrong:', error);Further reading
- FAQ — common errors and troubleshooting, including a detailed TinyGo error catalog
- Rust Language Guide — crate compatibility, version alignment, type conflict resolution
- Go (TinyGo) Language Guide — stdlib compatibility,
wasm-toolspinning, project configuration - TypeScript Language Guide — library compatibility, StarlingMonkey APIs, build pipeline
- Useful WebAssembly Tools —
wasm-tools, Wasmtime, WASI Virt, and other ecosystem tools - Command Reference — full
washCLI reference including--verboseand--log-levelflags