Releases: cloudflare/workers-sdk
Release list
wrangler@4.106.0
Minor Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Addwrangler ai-search jobscommands for managing AI Search indexing jobsYou can now list, trigger, inspect, cancel, and read the logs of indexing jobs for an AI Search instance:
wrangler ai-search jobs list <instance> wrangler ai-search jobs create <instance> --description "manual reindex" wrangler ai-search jobs get <instance> <job-id> wrangler ai-search jobs cancel <instance> <job-id> wrangler ai-search jobs logs <instance> <job-id>All commands accept
--namespace/-n(defaults todefault). All commands exceptcancelalso accept--jsonfor clean machine-readable output. -
#14490
75d8cb0Thanks @petebacondarwin! - Add--source-jurisdictiontowrangler ai-search createfor R2-backed instancesR2 buckets can live in a specific jurisdiction (for example
euorfedramp). You can now point an AI Search instance at a bucket in one of those jurisdictions:wrangler ai-search create my-instance --type r2 --source my-bucket --source-jurisdiction euWhen run interactively, the R2 source flow also prompts for a jurisdiction and lists (and can create) buckets within it. The value is a free-form string forwarded to the API as
source_params.r2_jurisdiction(server-side validated); omit the flag for no specific jurisdiction. This AI Search command is in open beta. -
#14490
75d8cb0Thanks @petebacondarwin! - Add auth profiles for managing multiple OAuth loginsAuth profiles let you maintain separate OAuth logins and bind them to directories, so you can switch between different accounts for different projects without having to re-login.
For example:
wrangler auth create work wrangler auth activate work ~/projects/work wrangler auth create personal wrangler auth activate personal ~/projects/personal
New commands under
wrangler auth:wrangler auth create <name>— create or re-authenticate a named profile via OAuthwrangler auth delete <name>— delete a profile and all its directory bindingswrangler auth activate <name> [dir]— bind a profile to a directory (defaults to cwd). Sub-directories will inherit this profile.wrangler auth deactivate [dir]— remove a directory bindingwrangler auth list— list all profiles and their corresponding directories
There is also a new global
--profileflag, which you can use to activate a profile for just that command run. Note that if you haveCLOUDFLARE_API_TOKENset, that will still take precedence over all profiles. Any account id settings (viaCLOUDFLARE_ACCOUNT_IDor wrangler config) will also still be respected. -
#14490
75d8cb0Thanks @petebacondarwin! - Add--strictflag towrangler versions uploadand improve pre-upload safety checkswrangler versions uploadnow runs the same pre-upload checks aswrangler deploy:- When the Worker was last edited via the Cloudflare Dashboard, the local and remote configurations are diffed and you are warned only if the diff is destructive (previously, an unconditional warning was shown).
- When local configuration values conflict with remote secrets, a warning is shown before proceeding.
- When deploying workflows that belong to a different Worker, a warning is shown before proceeding.
The new
--strictflag (already available onwrangler deploy) causeswrangler versions uploadto abort in non-interactive/CI environments when any of these conflicts are detected, instead of auto-continuing. -
#14490
75d8cb0Thanks @petebacondarwin! - Add D1 migration setup tocreateTestHarness()Worker handlesTests using
createTestHarness()can now apply local D1 migrations before running requests:const worker = server.getWorker(); beforeEach(async () => { await worker.applyD1Migrations("DATABASE"); });
-
#14490
75d8cb0Thanks @petebacondarwin! - Add Workflow introspection tocreateTestHarness()Worker handles can now introspect Workflow bindings by name, allowing tests to disable sleeps, mock step results, and wait for Workflow outcomes. Tests can introspect a known Workflow instance by ID or track instances created after introspection starts.
const harness = createTestHarness({ workers: [{ configPath: "./wrangler.json" }], }); const worker = harness.getWorker(); await using workflow = await worker.introspectWorkflow("MY_WORKFLOW"); await workflow.modifyAll((modifier) => modifier.disableSleeps([{ name: "wait-for-approval" }]) ); const response = await worker.fetch("/start-workflow"); const [instance] = await workflow.get(); await instance.waitForStatus("complete");
-
#14446
e0cc2cbThanks @edmundhung! - AddbindingOverridesandgetExport()tocreateTestHarness()Test harness workers loaded from Wrangler config files can now replace a configured binding with a Worker in the same harness. This is useful for replacing platform bindings with test Workers while keeping the source Worker config production-like. You can also call
getExport()on a Worker returned byserver.getWorker(name)to access JSRPC methods on the default Worker export, including mock Workers used as override targets.const server = createTestHarness({ workers: [ { configPath: "./workers/app/wrangler.jsonc", bindingOverrides: { BROWSER: "mock-browser" }, }, { // A mock Worker implementing the Browser Rendering binding named "mock-browser". configPath: "./workers/mock-browser/wrangler.jsonc", }, ], }); const mockBrowser = await server .getWorker<WebEnv, typeof import("./workers/mock-browser")>("mock-browser") .getExport(); await mockBrowser.setScreenshot(stubPng); const response = await server.fetch("/reports/2026-05-29.png"); expect(await response.bytes()).toEqual(stubPng);
-
#14490
75d8cb0Thanks @petebacondarwin! - Improvewrangler tailresilience and shutdown behaviourwrangler tailpreviously crashed with a raw stack trace when the keep-alive ping to the Worker timed out, and could exit with an ugly error on Ctrl-C.- Errors now flow through wrangler's usual error pipeline instead of escaping as uncaught exceptions.
- The keep-alive timeout message now clearly explains what happened and no longer prints a stack trace.
- When the tail connection drops unexpectedly,
wrangler tailnow automatically tries to reconnect with exponential back-off (up to 5 retries). - Ctrl-C now prints a short "Stopping tail..." message (in pretty mode), awaits the server-side tail deletion, and exits cleanly with code 0.
Patch Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260625.1 1.20260629.1 -
#14478
f10d4adThanks @dependabot! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260629.1 1.20260630.1 -
#14490
75d8cb0Thanks @petebacondarwin! - Improve the deploy warning shown when a Workflow name already belongs to another WorkerThe warning still notes that deploying reassigns the workflow to the current Worker, and now also explains why this happens (workflow names must be unique per account) and how to resolve it (rename the workflow in the Wrangler config).
-
#14490
75d8cb0Thanks @petebacondarwin! - usestreaminstead of deprecatedpipelinekey ...
miniflare@4.20260630.0
Patch Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260625.1 1.20260629.1 -
#14478
f10d4adThanks @dependabot! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260629.1 1.20260630.1 -
#14490
75d8cb0Thanks @petebacondarwin! - Fix edge cases on the local R2 public bucket endpoint (/cdn-cgi/local/r2/public) to match r2.dev: write methods are rejected with 401, malformed/multiple/inverted ranges with 400 and unsatisfiable ranges (includingbytes=-0) with 416,Rangeis honored on HEAD requests with a bodyless 206,Content-Rangeis correct for suffix ranges, object keys are percent-decoded exactly once (keys containing a literal%no longer fail), and objects stored without a content type are served asapplication/octet-streaminstead of omitting theContent-Typeheader. Unread object bodies are also cancelled (on HEAD and unsatisfiable-range responses) instead of leaking a read stream until garbage collection. -
#14490
75d8cb0Thanks @petebacondarwin! - Add Workflow introspection tocreateTestHarness()Worker handles can now introspect Workflow bindings by name, allowing tests to disable sleeps, mock step results, and wait for Workflow outcomes. Tests can introspect a known Workflow instance by ID or track instances created after introspection starts.
const harness = createTestHarness({ workers: [{ configPath: "./wrangler.json" }], }); const worker = harness.getWorker(); await using workflow = await worker.introspectWorkflow("MY_WORKFLOW"); await workflow.modifyAll((modifier) => modifier.disableSleeps([{ name: "wait-for-approval" }]) ); const response = await worker.fetch("/start-workflow"); const [instance] = await workflow.get(); await instance.waitForStatus("complete");
create-cloudflare@2.70.7
Patch Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To create-vike 0.0.654 0.0.660 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To nuxi 3.35.2 3.36.1 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To create-vite 9.0.7 9.1.0 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To @tanstack/cli 0.69.3 0.69.5 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To @angular/create 22.0.3 22.0.4 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To create-astro 5.0.6 5.2.0 -
#14490
75d8cb0Thanks @petebacondarwin! - Update dependencies of "create-cloudflare"The following dependency versions have been updated:
Dependency From To create-analog 2.6.1 2.6.2 -
#14490
75d8cb0Thanks @petebacondarwin! - Fix npm installs for Analog projectsAnalog's generated Vite overrides can cause npm to fail with
Unable to resolve reference $vitewhen dependency resolution changes.create-cloudflarenow opts npm-generated Analog projects out of those overrides so project creation can complete successfully.
@cloudflare/vitest-pool-workers@0.17.0
Minor Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Make Workflow introspectorget()asyncThe
introspectWorkflow(...).get()method now returns a promise, so callers must await it:const introspector = await introspectWorkflow(env.MY_WORKFLOW); // Before const instances = introspector.get(); // After const instances = await introspector.get();
This aligns Workflow introspection with the shared implementation used by
createTestHarness().
Patch Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Supportrequire("./x.wasm?module")in CommonJS dependenciesPreviously, only literal
await import("./x.wasm?module")specifiers were rewritten through the static analysis path added in #11094. CommonJS dependencies that userequire("./x.wasm?module")reach the module-fallback service at runtime, where the?modulesuffix went unhandled. The fallback either failed withNo such module "<abs>/x.wasm?module"or, when aCompiledWasmrule was configured, attempted to evaluate the WebAssembly bytes as JavaScript.However, these
require()s work in deployed workers because esbuild's bundler statically rewrites theserequire()calls into ES dynamic imports. vitest-pool-workers' Vite-based pipeline doesn't do that rewrite and instead defers to the module-fallback at runtime.The module-fallback now strips
?modulefrom the resolved target and synthesizes a CommonJS wrapper that re-requires the underlying.wasmby absolute path, exposing it ondefaultto match what workerd produces forCompiledWasmmodules. -
Updated dependencies [
75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,f10d4ad,75d8cb0,75d8cb0,75d8cb0,75d8cb0,d292046,75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,e0cc2cb,75d8cb0,75d8cb0,75d8cb0]:- wrangler@4.106.0
- miniflare@4.20260630.0
@cloudflare/vite-plugin@1.42.4
Patch Changes
-
#14490
75d8cb0Thanks @petebacondarwin! - Preserve D1 migration paths in generated Worker configsWhen a Worker config with a D1 binding is built by the Vite plugin, the generated
wrangler.jsonnow pointsmigrations_dirback to the source migration directory. This lets tools that read the generated config, such ascreateTestHarness(), find the same D1 migrations as the source Worker config. -
Updated dependencies [
75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,f10d4ad,75d8cb0,75d8cb0,75d8cb0,75d8cb0,d292046,75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,75d8cb0,e0cc2cb,75d8cb0,75d8cb0,75d8cb0]:- wrangler@4.106.0
- miniflare@4.20260630.0
@cloudflare/deploy-helpers@0.2.5
wrangler@4.105.0
Minor Changes
-
#14311
34e0cefThanks @sherryliu-lsy! - Add Google Artifact Registry support tocontainers registries configurewrangler containers registries configurenow recognizes*-docker.pkg.dev(Google Artifact Registry) domains.- The Google service account email is the public credential, supplied with
--gar-email. It must match theclient_emailin the service account key. - The service account JSON key is the private credential. It is provided via stdin (a file path, raw JSON, or base64) or an interactive prompt (a file path or base64) — never as a CLI flag, so it does not appear in shell history. The key is validated against
--gar-emailand stored base64-encoded. - Secret reuse inherits the existence-first flow: when the target Secrets Store secret already exists, it is reused by reference and the key is not required. In that case the email cannot be verified locally; it is validated against the key when images are pulled.
<path-to-key>.json | npx wrangler@latest containers registries configure <region>-docker.pkg.dev --gar-email=<service-account-email> --secret-name=Google_Service_Account_JSON_Key
- The Google service account email is the public credential, supplied with
Patch Changes
-
#14424
5f40dd5Thanks @MattieTK! - Bumpam-i-vibingfrom 0.4.0 to 0.5.0This updates the agentic environment detection library to the latest version, which adds detection for the Pi coding agent (
earendil-works/pi). -
#14406
3b743c1Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260623.1 1.20260625.1 -
#14343
daa5389Thanks @th0m! - Use digest-pinned image references for Dockerfile container deploysDockerfile-backed container deploys now use the pushed image digest when deploying the container application. This lets snapshot-enabled container apps pass Cloudchamber validation while keeping local, non-pushed builds and registry image URI deploys unchanged.
-
#14394
8a5cf8cThanks @Partha-Shankar! - fix(d1): escapemigrationsTableNameand filenames in SQLite queriesD1 migration commands in both
wranglerand@cloudflare/vitest-pool-workersinterpolated themigrationsTableNameconfig value and migration filenames directly into SQL strings without any escaping. This meant:- A table name such as
my"tablewould produce invalid SQL inCREATE TABLE,SELECT, andINSERTstatements, and - A migration filename containing an apostrophe (e.g.
what's-new.sql) would break theINSERT INTO ... VALUES ('...')statement appended after each migration inwrangler.
Both identifiers are now properly escaped before interpolation:
migrationsTableNameis wrapped in double-quotes with internal double-quotes doubled (SQL-standard identifier quoting), and migration filenames used as string literals have their single-quotes doubled before insertion. - A table name such as
-
Updated dependencies [
3b743c1]:- miniflare@4.20260625.0
miniflare@4.20260625.0
Patch Changes
-
#14406
3b743c1Thanks @dependabot! - Update dependencies of "miniflare", "wrangler"The following dependency versions have been updated:
Dependency From To workerd 1.20260623.1 1.20260625.1
@cloudflare/vitest-pool-workers@0.16.20
Patch Changes
-
#14398
c5014ccThanks @apeacock1991! - AddevictDurableObjectandevictAllDurableObjectstest helpers tocloudflare:testThese helpers let you exercise how a Durable Object behaves across evictions in your tests. Eviction is graceful: durable storage is preserved, in-memory state is reset by tearing down the instance, hibernatable WebSockets are hibernated rather than closed, and eviction waits for in-flight requests to drain.
import { evictDurableObject, evictAllDurableObjects } from "cloudflare:test"; import { env } from "cloudflare:workers"; const id = env.COUNTER.idFromName("my-counter"); const stub = env.COUNTER.get(id); // Evict the Durable Object instance pointed to by a specific stub await evictDurableObject(stub); await evictDurableObject(stub, { webSockets: "close" }); // Evict all currently-running Durable Objects in evictable namespaces await evictAllDurableObjects();
-
#14394
8a5cf8cThanks @Partha-Shankar! - fix(d1): escapemigrationsTableNameand filenames in SQLite queriesD1 migration commands in both
wranglerand@cloudflare/vitest-pool-workersinterpolated themigrationsTableNameconfig value and migration filenames directly into SQL strings without any escaping. This meant:- A table name such as
my"tablewould produce invalid SQL inCREATE TABLE,SELECT, andINSERTstatements, and - A migration filename containing an apostrophe (e.g.
what's-new.sql) would break theINSERT INTO ... VALUES ('...')statement appended after each migration inwrangler.
Both identifiers are now properly escaped before interpolation:
migrationsTableNameis wrapped in double-quotes with internal double-quotes doubled (SQL-standard identifier quoting), and migration filenames used as string literals have their single-quotes doubled before insertion. - A table name such as
-
Updated dependencies [
5f40dd5,34e0cef,3b743c1,daa5389,8a5cf8c]:- wrangler@4.105.0
- miniflare@4.20260625.0