windmill-labs/windmill · warning

${existingName}: ${wired}. Add ${opts.hint} manually to pick

Error message

${existingName}: ${wired}. Add ${opts.hint} manually to pick up wmill's recommended settings (incl. workspace /f/, /u/ import resolution).

What it means

During `wmill refresh tsconfig` (or the Deno import-map variant), wmill tries to merge its recommended compiler settings into an existing tsconfig.json via opts.wire(). The merge is non-mutating: if the custom config cannot be wired (e.g. an 'extends' chain or non-object fields prevent inserting the needed entries), wmill warns instead of silently rewriting the file and asks the user to add the setting manually so workspace /f/ and /u/ import paths resolve.

Source

Thrown at cli/src/commands/refresh/tsconfig.ts:377

  // The file is still exactly what a previous CLI generated → it's ours, so
  // migrate it to the new split (replace with the thin stub that extends the
  // managed file). No prompt: we're not touching user-authored content.
  if (opts.legacyFormats?.some((fmt) => deepEqual(parsed, fmt))) {
    writeFileSync(existing, JSON.stringify(opts.create, null, 2) + "\n");
    log.info(
      colors.green(
        `Migrated previously-generated ${existingName} to reference ${opts.token}`
      )
    );
    return;
  }

  // Custom config. Try wiring a clone so we can report un-wireable cases without
  // mutating, then only persist with the user's consent.
  const next = JSON.parse(JSON.stringify(parsed)) as Record<string, unknown>;
  const wired = opts.wire(next);
  if (wired !== true) {
    log.warn(
      `${existingName}: ${wired}. Add ${opts.hint} manually to pick up wmill's ` +
        `recommended settings (incl. workspace /f/, /u/ import resolution).`
    );
    return;
  }

  const consent = opts.mode.assumeYes
    ? true
    : opts.mode.interactive
    ? await Confirm.prompt({
        message:
          `${existingName} isn't linked to wmill's ${opts.token}. Add ${opts.hint}? ` +
          `Your settings are preserved (it's inserted first, so your config wins).`,
        default: true,
      })
    : false;

  if (!consent) {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Open tsconfig.json and add the setting named in the warning (per opts.hint, e.g. paths / baseUrl entries) by hand
  2. Temporarily rename or simplify tsconfig.json, re-run `wmill refresh tsconfig` to get a working baseline, then re-apply custom settings on top
  3. Check for an 'extends' preset blocking the merge and inline the needed compilerOptions instead

Example fix

// before (tsconfig.json)
{ "extends": "@tsconfig/svelte/tsconfig.json" }
// after
{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "/f/*": ["./.wmill/gen/frontend/*"], "/u/*": ["./.wmill/gen/user/*"] }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

const cfg = JSON.parse(fs.readFileSync('tsconfig.json','utf8')); if (cfg.extends) console.warn('preset may block wmill wiring');

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> { return typeof v === 'object' && v !== null && !Array.isArray(v); }

Prevention

When it happens

Trigger: Running `wmill refresh tsconfig` (or `wmill refresh deno-import-map`) in a project whose tsconfig.json is too custom for the automatic wiring — typically a config extending a third-party preset the merger cannot traverse, or conflicting entries it refuses to overwrite.

Common situations: Projects using tsconfig presets (SvelteKit, Vite, Nx) where 'extends' hides the real config; monorepos with hand-tuned compilerOptions; CI refresh runs where the local tsconfig drifted from the one wmill generated earlier.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/2dcc642d6f8d9f65. Report an issue: GitHub.