Troubleshooting
Start with the first diagnostic owner and code. Tsonic does not hide an error by emitting partial target code.
A required command is missing
create-tsonic checks the selected target before publishing the project. Its
diagnostic names the failed command and links to the official installer. If a
toolchain was changed after creation, run the same checks manually.
Check the host tools first:
node --version
npm --version
For C#, dotnet --list-sdks must include a 10.0.x SDK. Installing only a
.NET runtime is insufficient. Use the
official .NET installer
or Microsoft’s platform instructions.
For Rust, the required commands must resolve from one rustup toolchain:
rustup show active-toolchain
rustc --version
cargo --version
rustdoc --version
rustfmt --version
Use the official rustup installer,
then run rustup component add rustfmt. Tsonic does not substitute a different
formatter, compiler, or metadata producer when one is missing. If an optional
cargo clippy command is unavailable, run rustup component add clippy.
Target not found
Target 'rust' is not installed
Install the target in the package containing tsonic.json:
npm install --save-dev @tsonic/target-rust@^0.1.0
Tsonic discovers plugins from installed direct dependencies,
devDependencies, and optionalDependencies. A target id in tsonic.json
does not install the package.
Check discovery:
npx --no-install tsonic targets --project tsonic.json
For a new project, prefer npm create tsonic@latest <directory> -- --target rust; the creator installs and validates the target as one transaction.
Cache directory is not writable
Targets never write inside installed packages. Their compiler-tool state goes
under .tsonic/cache beside tsonic.json by default. Select another writable
path when needed:
{
"cacheDir": "../cache/example-tsonic"
}
cacheDir cannot be equal to, inside, or contain outDir.
A global or built-in is missing
If console, Map, or JavaScript string methods are missing, select the JS
surface:
{ "id": "csharp", "surfaces": ["js"] }
If a node:* import is missing, install the target’s Node capability package.
Installing Node does not select the JS surface.
A C# executable does nothing
C# applications run top-level entry-module code. This only declares a function:
export function main(): void {
// Not called automatically by the C# target.
}
Call it, or put startup work at top level:
main();
A Rust binary has no entrypoint
The entry module must contain:
export function main(): void {}
The function must be exported and return void.
Cargo rejects --locked
Generate source, then run one command without --locked, or create the
lockfile explicitly:
cargo generate-lockfile --manifest-path out/rust/Cargo.toml
cargo build --manifest-path out/rust/Cargo.toml --locked
The lockfile is inside compiler-owned outDir; the next successful
tsonic build replaces it. Use a user-owned Cargo project when the lockfile
must be retained in version control.
A .NET type imports but does not link
Provider inputs and build references are separate. providerReferences makes
an assembly available to metadata reflection. Add the corresponding project,
package, framework, or assembly under references so the generated project can
compile and link it.
A Rust crate import is missing
Third-party Rust imports use a direct dependency alias from a user-owned
Cargo.toml:
[dependencies]
widget_alias = { package = "acme-widget", version = "1.2.3" }
import { Widget } from "@tsonic/rust/crates/widget_alias/index.js";
The alias must be a direct dependency. Tsonic does not search transitive crates or infer a package from an import spelling.
A tsconfig option is rejected
Move module aliases to real package exports. Tsonic intentionally rejects
compilerOptions, paths, baseUrl, extends, and TypeScript project
references.
The previous output is still present
That is intentional after a failed build. Tsonic publishes output transactionally. A failed build does not replace the last complete output.
Native compilation fails
Read the native compiler output first. Tsonic owns generated source validity; the native compiler remains authoritative for SDK installation, target packs, linkers, system libraries, Cargo dependencies, borrow checking, and native project configuration.
See diagnostics and the target’s C# limitations or Rust limitations.