1.18.x
October 2, 2026
BoxLang 1.18.0 is a big release pushing forward our development mantra: BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together. This release delivers two headline features: a brand new Azure Functions runtime that completes the serverless trio with AWS Lambda and Google Cloud Functions, and server fixation for scheduled tasks, so a clustered deployment runs each task exactly once. It also hardens the AWS Lambda and Google Cloud Functions runtimes, adds a CLI that scripts and agents can drive, new class instantiation interception points, and a long list of CFML-compatibility and JDBC correctness fixes.
BoxLang 1.18.0 also includes every hotfix released since 1.17.0 (1.17.1 through 1.17.6). If you are on any 1.17.x patch, you already have those fixes. See Included Hotfixes for the full list.
🚀 Major Highlights
☁️ Azure Functions Runtime (BL-2107)
BoxLang is now a first-class citizen on Microsoft Azure Functions. Together with AWS Lambda and Google Cloud Functions, BoxLang now runs serverless on all three major clouds from one codebase.
What you get:
One handler contract everywhere.
run( event, context, response )is identical on AWS, Google and Azure, so your.bxcode moves between providers unmodified.Convention-based routing. Handlers live in
handlers/, a build-timemanifest.jsonis the routing table, and thex-bx-functionheader selects a method.A turnkey starter project with Gradle dependency management, unit and integration testing, class compilation caching, configuration with environment overrides, the official Azure Functions Gradle plugin for local run and deploy, and GitHub Actions to test, build and release.
The full
Application.bxlifecycle withonRequestStart,onRequestEnd,onErrorandonAborthooks, automatic request mapping to aneventstruct, logging and tracing, and automatic JSON response serialization.Azure-aware defaults. The runtime root comes from
BOXLANG_AZURE_ROOTand falls back to theAzureWebJobsScriptRootthat the Azure host sets.
🔒 Scheduled Tasks: Server Fixation for Clusters (BL-2653)
Scheduled tasks are now cluster-safe. Deploy the same Scheduler.bx to every node and, with one call, make sure each task runs on exactly one server per firing. Before 1.18, a task scheduled with everyDayAt( "02:00" ) ran once per node, which is rarely what you want for nightly cleanups, report generation or cache warming.
How it works:
Distributed lock. When a task is due, every node races to write a lock key into the scheduler's
cacheNamecache. The first write wins and runs the task; every other node skips that cycle.Crash-safe. The lock is left to expire instead of being released, so if the winning node dies mid-run, a surviving node can take the next scheduled run instead of the cluster being locked out.
Sized to the real schedule. Lock lifetime is computed from the task's actual recurrence, including monthly and business-day constraints, not from the scheduler's short internal polling interval. A monthly task cannot be re-run the same day by a second node.
Observable. After a run,
getStats()includesinetHostandlocalIp, showing which server won.Bring your own cache. Point
cacheNameat a cache the servers share, such as Redis viabx-redis:
The scheduler also got a reliability pass:
BL-2654 - Fixed
.between()combined with.everyHour()re-firing.BL-2534 - Fixed "A scheduler with the name [bxschedule] already exists".
BL-2673 - Errors in a custom task failure function or
finallyblock can no longer disable a scheduled task.BL-2700 - Fixed a concurrent modification exception in
schedule.doList().everyMonthOn( 31 )now clamps to the last day of shorter months instead of firing every day of that month.
🛡️ AWS Lambda and Google Cloud Functions Runtime Updates
The serverless runtimes share one hardened design across all three clouds:
Secure routing (BL-2711). Only files under
handlers/, or listed in the build-timemanifest.json, are routable. Earlier runtimes routed to any.bxfile at the project root, includingApplication.bxandLambda.bx, which let an unauthenticated request reach lifecycle callbacks and other public methods through thex-bx-functionheader. SetBOXLANG_ENABLE_ROOT_SCAN=falseto disable the legacy root-scan fallback entirely.Lifecycle hooks receive the response.
run(),onRequestStart,onRequestEnd,onErrorandonAbortall receive the sameresponsestruct, so oneonRequestEndcan wrap every result in a standard envelope andonErrorcan shape errors. BL-2516 fixes AWS Lambda hooks having no access to the request and response.Response modes.
httpmode (default) pre-seedsstatusCode,headers,bodyandcookies;rawmode returns your value as is. SetBOXLANG_RESPONSE_MODEtohttporraw.Handled errors. An error handled by
onErrordefaults the status to500, which you can change withresponse.statusCode.Cleaner response object. BL-2517 removes the extra properties from the pre-generated AWS Lambda response object.
Documented end to end. New sections cover the
handlers/convention,manifest.json, the application lifecycle, and theGCLOUD_PROJECTfallback for Google Cloud Functions.
🖥️ A CLI That Scripts and Agents Can Drive
BL-2699 -
.boxlang.jsonauto-discovery. The CLI runner now picks up a.boxlang.jsonin the current working directory when no config was supplied. An explicitBOXLANG_CONFIGenvironment variable or--bx-configflag always wins. See Customizing boxlang.json for the full lookup order, per-project and per-user files, and how it compares to.envfiles.BL-2652 / BL-1270 -
boxlang schedulereports. Runningboxlang schedulewith no arguments now prints a report of scheduler configuration, loaded schedulers and their tasks, and persisted tasks instead of throwing. Add--jsonfor a machine-readable document you can pipe intojqor hand to an agent. Credentials are stripped from the output.BL-2663 -
-h,--helpand--versionno longer swallow a following module name, soboxlang bxSites -hroutes to the module.BL-2701 - Clearer error when a module requested from the CLI is missing.
🔌 New Interception Points: afterBoxClassCreation and afterBoxClassInit (BL-2705)
Two new interception points let interceptors observe BoxLang class instantiation:
afterBoxClassCreation
When an instance is fully defined (pseudo-constructor ran, interfaces and abstract methods validated) but before init(). Also fires for noInit creations such as createObject() and deserialization. Never fires for super classes in an extends chain.
instance, className, noInit, context
afterBoxClassInit
After init() (or the implicit constructor) completes. Does not fire for noInit creations or when init() throws.
instance, result, className, context
These are the hooks for dependency injection, auditing, and observability layers.
✅ CFML Compatibility: cflock type="exclusive" Is Exclusive Again (BL-2686)
The CFML transpiler mapped type="write" to exclusive, then mapped every other value that was not "readonly" down to "readonly", which caught "exclusive" itself. CFML-source locks written with type="exclusive" were silently compiled to read locks. That includes WireBox's Singleton.cfc double-checked locking, where the lock is the only protection against duplicate singleton construction under concurrency. This shipped in 1.17.6 and is included here. The mapping is now:
writebecomesexclusiveexclusive(any case) staysexclusivereadonlystaysreadonlyanything else becomes
readonly(CF's lenient default)
🤖 The AI-Native Platform
BoxLang is built for developers and the AI agents working beside them. The platform pieces below were documented and published alongside 1.18:
Agentic Development
Set up your project, skills, MCP servers and IDE so an agent is productive from the first prompt.
Fast validation
boxlang check validates syntax without running code, so agents can verify every edit.
Skills
Installable SKILL.md playbooks for BoxLang, ColdBox, TestBox, CommandBox and modules.
BoxLang AI
Chat, agents, tools, memory, RAG, MCP, multimodal and governance through one fluent API.
bx-playwright
Fluent browser automation and testing, browser tools for AI agents, and HTML to PDF/image rendering.
bx-search (BoxLang+)
Full-text search with Elasticsearch, OpenSearch and Solr providers, CFML-compatible components, and a fluent SearchNew() BIF.
Agentic web apps
The fastest path to a BoxLang web application built with an agent.
✨ New Features and Improvements
Dates and Time (BL-2689)
Set a single unit of a date/time value without rebuilding it. Every unit is available as a dateSet*() BIF and as a member method; both mutate the date in place and return it.
Out-of-range values roll over into the next unit (setDay( 50 ) advances into following months), while zero or negative values clamp to the first valid unit (setDay( 0 ) becomes day 1). Reference: dateSetYear, dateSetMonth, dateSetDay, dateSetHour, dateSetMinute, dateSetSecond.
Async
BL-2685 -
BoxFuture.allApply()has an overload that does not require an error handler:BoxFuture::allApply( myArray, ( item ) => processItem( item ) ).BL-2659 -
runAsync(),asyncAll()andasyncAllApply()now isolate their JDBC connection and transaction instead of sharing the caller's.BL-2696 -
bx:threadmetadata (status,elapsedTime,stackTrace) is computed on read instead of tracked continuously. A stack trace is expensive to capture and was previously paid on every unscoped variable lookup inside a thread.BL-2681 - Fixed a
RequestThreadManagercompletion race that could cause an infinite CPU spin.
JDBC and Queries
BLMODULES-300 - New global
GenericJDBCDriver.representBitAsBooleanflag (defaultfalse). When enabled from Java code or a module,BITvalues in query objects are true booleans instead of1/0. There is noboxlang.jsonsetting for it yet. Builds on the bit-casting consistency fix BL-2674 from 1.17.4.BL-2661 - HikariCP upgraded to 7.1.0.
BL-2676 - JDBC parameter
scaleandmaxLengthaccept valid numeric values that are not Java Integers.BL-2690 - Non-bit columns no longer attempt a failing cast to boolean.
BL-2691 - Date detection for query params recognizes any Java date/time type; fixed a column type lookup bug with duplicate column labels.
BL-2679 - Improved proc debugging.
Language and Runtime
BL-2675 - The
paramstatement now evaluates its default expression only when the variable does not already exist.BL-2628 - Property merging from a parent class happens exactly once per class, even when two threads instantiate a freshly compiled subclass at the same moment. Fixes missing generated accessors.
BL-2457 - Fixed nested
switchstatements returning incorrect values.BL-2649 -
array.toSet( "linked" )preserves the original array order.BL-2523 -
structFindKey()descends into arrays.BL-2688 - Internal boxpiler build refactor.
Performance
BL-2697 -
replace( ..., "all" )exits early when the substring never appears and avoids repeated allocation.BL-2670 -
isDate()is faster on non-dates.
Web, Sessions and Files
BL-2709 -
application action="update"keeps the request's live session instead of swapping in the cached copy, which lost writes with serializing session stores such as Redis.BL-2664 - Session persistence no longer runs after a redirect has already been sent.
BL-2682 - Fixed whitespace compression corrupting SSE responses.
BL-2662 - Whitespace management no longer strips the LF from CRLF.
BL-2651 -
?&no longer produces an empty URL variable.BL-2656 - Included template URLs are trimmed.
BL-2703 -
FileUploadno longer fails on an emptyOptional.BL-2683 - File reads (
BoxFile,fileRead(),loop file=...) no longer stop at the first byte sequence invalid for the charset.
CFML Compatibility
BL-2686 - See Major Highlights.
BL-2684 -
bx:transaction/cftransaction: exactaction="begin"detection, corrected commit/rollback/cleanup order, andcommit,rollbackandsetsavepointno-op when no transaction is active.BL-2713 - BigDecimal and BigInteger casters ignore leading zeros.
BL-2657 -
parseDateTime( "2/5/2026 12:00:00 AM" )parses.BL-2658 -
structGet()unwraps query columns.BL-2660 - Additional CF compatibility for XML features.
BL-2665 - Query nulls serialize to JSON as empty strings, as Adobe does.
BL-2593 - UU encoding and decoding handle strings and byte arrays correctly.
BL-2702 -
listEach()passes the original list string as the third closure argument, not an array.BL-2569 - Java exception
messageis an empty string rather than null.
Modules
bx-mail - BL-2708: multipart mail structure and charset handling when
charset=utf-8is set.bx-spreadsheet - BL-2668:
SpreadsheetAddRow()retains empty list elements.bx-plus - BL-2669: no longer requires the
.seedfile to exist.
🩹 Included Hotfixes
BoxLang 1.18.0 contains all of the following patch releases. Full details are on the 1.17.x page.
⚡ Migration Notes
cflock type="exclusive"is now actually exclusive. CF-transpiled code (and libraries such as WireBox's singleton scope) that relies ontype="exclusive"now blocks concurrent access. If anything depended on the old behavior, re-verify under load; you may see more lock contention.Invalid characters no longer truncate a file read. Code that relied on reads stopping at the first byte sequence invalid for the charset will now continue with the Unicode replacement character substituted.
The CLI now reads
./.boxlang.json. If a.boxlang.jsonsits in the directory you runboxlangfrom, it is now loaded. SetBOXLANG_CONFIGor--bx-configto override it.application action="update"keeps the live session. Session writes made during the request are no longer lost with serializing session stores.paramdefaults are lazy. The default expression is no longer evaluated when the variable already exists. Defaults with side effects will no longer run in that case.
📊 Release Snapshot
Release Date: October 2, 2026
Status: Released
Total Issues: 67
Distribution: 8 New Features, 15 Improvements, 43 Bugs, 1 Task
Primary Focus: Azure Functions runtime, scheduler server fixation, Lambda and Google runtime hardening, CLI automation, class instantiation interception points, CFML and JDBC correctness, and the AI-native platform story
🎶 Release Notes
BL-1270 - boxlang schedule should return usage info
BL-2107 - Create the Azure Functions Runtime Plan
BL-2457 - Nested switch statements returning incorrect values
BL-2516 - AWS Lambda - no access to request and response in Application.cfc methods
BL-2517 - AWS Lambda - pre-generated response object has too many properties
BL-2523 - StructFindKey Not Returning Items in Array
BL-2534 - A scheduler with the name [bxschedule] already exists
BL-2569 - Compat: Java Exception
messageobject is null vs empty stringBL-2593 - UU Encoding/Decoding Not Correctly Handling Strings and Byte Arrays
BL-2628 - generated accessors missing when a freshly compiled subclass is instantiated in parallel
BL-2649 - array.toSet( "linked" ) loses original array order
BL-2651 - ?& causes empty url var
BL-2652 - boxlang schedule: print a scheduler/tasks report (text or --json) when run with no scheduler file
BL-2653 - Server fixation / DELAY issue
BL-2654 - .between() + .everyHour() re-fire issue
BL-2656 - Trim included template URL
BL-2657 - Compat: parseDateTime( "2/5/2026 12:00:00 AM" ) fails
BL-2658 - structGet() doesn't unwrap query column
BL-2659 - runAsync does not get a fresh database connection
BL-2660 - Missing CF compat for XML Features
BL-2661 - Upgrade HikariCP to 7.1.0
BL-2662 - Whitespace managment stripping the LF from CRLF
BL-2663 - CLI:
-h/--help/--versionswallow a following module name instead of routing to it (e.g.boxlang bxSites -h)BL-2664 - Session persistence runs after redirects have been sent to browser
BL-2665 - Adobe doesn't convert query nulls to empty string on JSON serialization
BL-2666 - Improve listAppend() performance when includeEmptyFields=false
BL-2667 - file component action="write" is supposed to default relative paths to tmp dir
BL-2668 - SpreadsheetAddRow() needs to retain empty list elements
BL-2669 - bx-plus currently needs the .seed file to always exist
BL-2670 - improve isDate() performance on non-dates
BL-2671 - listAppend() regression
BL-2672 - Guard against exception cause circular reference
BL-2673 - Errors in custom task failure function or in finally block can disable scheduled task
BL-2674 - Bit columns across databases are not consistently cast
BL-2675 - Param statement evaluates its default expression when the variable already exists
BL-2676 - JDBC parameter scale and maxLength reject valid numeric values that are not Java Integers
BL-2677 - clob/blob values manually added to query incorrect
BL-2678 - .__ in number format not forcing trailing zeros
BL-2679 - Improve proc debugging
BL-2681 - RequestThreadManager completion race causes an infinite CPU spin
BL-2682 - Whitespace compression corrupts SSE responses; no per-application override
BL-2683 - loop over file fails with invalid bytes
BL-2684 - Better transaction CF compat
BL-2685 - Add an allApply() to the BoxFuture() that doesn't require an error handler
BL-2686 - clock race condition
BL-2687 - restore JSON interception announcement
BL-2688 - Refactor boxpiler build
BL-2689 - Compat: New Date Member Functions and BIFs
BL-2690 - Non-bit columns can sometimes attempt a failing cast to boolean
BL-2691 - TimeStamp not being recognized as a date in query param
BL-2692 - Off-by-one error when transforming query column values
BL-2693 - numberFormat() / lsNumberFormat(): rounding, request locale and default mask differ from Lucee / Adobe CF
BL-2694 - numberFormat(): result is not left-padded to the width of the mask (Adobe CF and Lucee both pad)
BL-2696 - ThreadComponentBoxContext.scopeFind captures a full Java stack trace on every scope lookup inside a thread body
BL-2697 - improve performance of replace()
BL-2699 - CLI: Auto-discover .boxlang.json config file in the current working directory
BL-2700 - Concurrent modification exception in schedule.doList()
BL-2701 - Better error when missing module from CLI
BL-2702 - ListEach - Third Argument of the original string list is an array
BL-2703 - FileUpload.java calls Optional.get() on empty Optional
BL-2704 - Floating point issue with queryparam
BL-2705 - New interception points: afterBoxClassCreation and afterBoxClassInit for BoxLang class instantiation
BL-2708 - bx-mail: multipart mails are built as
multipart/mixedwith mislabelled parts and ISO-8859-1 bodies althoughcharset=utf-8is setBL-2709 - application action="update" swaps the request's session for the cached copy with a serializing session store (Redis): session writes lost, onSessionStart fires twice
BL-2711 - Security: restrict Lambda/GCF URI routing to registered handlers
BL-2713 - BigDecimal and BigInteger caster don't ignore leading zeros
BLMODULES-300 - Allow opt-in to represent query bit as boolean or int
Last updated
Was this helpful?
