What's Changed
[1.5.4] — 2026-08-31
Added
- AppSync —
APPSYNC_JSresolvers execute — resolver code was stored and never run;request()now decides what the data source is asked for andresponse()shapes the answer, withutil.error,util.appendErrorandruntime.earlyReturnfollowing AWS in both of its documented positions, pipeline resolvers threadingctx.stash, andextensions.evictFromApiCacherecorded back to the service.NONE,HTTP,AMAZON_DYNAMODBandAWS_LAMBDAdata sources execute; the remaining types refuse withNotImplemented. Evaluation runs on a pool of Node workers — one evaluation in flight per worker, a 30-second bound with kill-and-respawn, a heap cap, and resolver console output surfaced in the service log. Contributed by @jbschooley. - AppSync — queries are parsed and executed with
graphql-core— the regex data plane failed silently on aliases, fragments, nested selection sets, variables with defaults and directives; an API with a schema now parses, validates and executes with the reference engine (an AppSync prelude supplies theAWS*scalars and@aws_*directives), while a schemaless API keeps the previous lenient path. Addsgraphql-coreas a dependency. Contributed by @jbschooley. - AppSync — schema creation, pipeline functions, environment variables and the
Update*operations —StartSchemaCreation,GetSchemaCreationStatus,GetIntrospectionSchema(SDL verbatim, or a real introspection document forformat=JSON), the function operations,Put/GetGraphqlApiEnvironmentVariablesandUpdateDataSource/UpdateResolver/UpdateFunction/UpdateTypeall answeredUnsupported route.CreateGraphqlApialso omittedapiType,visibilityandintrospectionConfigand left tags off the API object, so a no-change Terraform plan proposed replacing the API; required members are validated rather than silently defaulted. Contributed by @jbschooley. - AppSync — the API cache, control plane and data plane — the five
ApiCacheoperations answeredUnsupported route; they now round-trip a record carryinghealthMetricsConfig, withttl(1–3600),apiCachingBehaviorandtyperequired and validated as on AWS, and the data plane serves query resolvers from the cache under both caching behaviors, mutations excluded. Contributed by @jbschooley. - AppSync — nested type resolvers,
ctx.identityfrom Cognito,ctx.envandctx.error— only top-levelQuery/Mutationfields resolved andctx.identitywas only ever set by a Lambda authorizer; a resolved value's type now runs its own resolvers with the parent asctx.source, a Cognito token populatesctx.identity, andresponse()sees a data source failure asctx.error. Contributed by @jbschooley. - AppSync — the
@aws-appsync/utils/dynamodbhelpers, andEvaluateCode— the helper sub-module was stripped with every other import, soddb.get/put/update/remove/scan/querydied with "ddb is not defined"; they are provided and bound to whatever name the import used, andEvaluateCodetests a handler before it is attached to an API. Contributed by @jbschooley. - AppSync —
util.transformDynamoDB expression builders and the rest of theutilsurface —util.transformwas an empty object and 8 of the 21 members@aws-appsync/utilsdeclares were provided;toDynamoDBFilterExpression/toDynamoDBConditionExpressionnow build the{expression, expressionNames, expressionValues}triple over AWS's documented operator set, and the missingutilmembers (base64*,url*,escapeJavaScript,matches,authType, realautoUlid/autoKsuid,util.str,util.math,util.time, theutil.dynamodbto*family,util.rds.toJsonObject) are implemented, with the rest refusing by name. Contributed by @jbschooley. - Aurora DSQL — foreign key constraints — every
REFERENCES/FOREIGN KEYclause was refused0A000; they now reach the backend as written, with the two DSQL-specific rules enforced against a live cluster (eu-central-1, 2026-08-30):ALTER TABLE ... ADD CONSTRAINT ... FOREIGN KEYmust useNOT VALID, andDEFERRABLEis refused on any other kind of constraint, in the service's own wordings. Contributed by @vivedo. - Aurora DSQL — change data capture streams, and
GetVpcEndpointServiceName— the four CDC stream operations answeredValidationException; streams now create, describe, list, page, tag and delete with the API's shapes (clientTokenidempotency, the 5-per-cluster quota asServiceQuotaExceededException). Metadata only: no change record reaches the Kinesis target, and a visibly broken target lands the streamFAILEDwith the service'sstatusReasoncode.GetVpcEndpointServiceNameanswers a stable per-cluster name. Contributed by @vivedo. - Aurora DSQL —
SELECT ... FOR KEY SHARE— refused0A000alongsideFOR SHAREandFOR NO KEY UPDATEalthough the live service takes it since 2026-08-25; it is now forwarded, and only the other two are refused. Contributed by @vivedo. - IoT Core —
ListThingGroupsForThing— the reverse lookup answeredUnsupported IoT path, so resolving a thing's groups meant scanning every group; it now returns{groupName, groupArn}pairs from the bidirectional membership store, withResourceNotFoundExceptionfor an unknown thing. The full list comes back in one page, like the service's other list operations. Contributed by @iot-rocket. - CloudFormation —
AWS::IoT::CACertificateprovisions onto the CA registry — a template declaring the type rolled the stack back withUnsupported resource type. The provisioner now drives the real API: create registers the PEM withRegistrationConfigandCertificateMode(stored and reported byDescribeCACertificate,DEFAULTwhen omitted), update appliesStatus/AutoRegistrationStatus/RegistrationConfig/RemoveAutoRegistrationin place, and delete deactivates first, because an ACTIVE CA refusesDeleteCACertificate. A PEM that is already registered fails the create, as CloudFormation does for an existing resource, and a changedCACertificatePemorCertificateModefails the update loudly rather than silently replacing the CA — the id is derived from the certificate content.Tagsare not modeled. Contributed by @iot-rocket. - KMS —
GenerateRandom— the one keyless KMS operation answeredInvalidAction; it now returns the requested 1–1024 bytes fromos.urandom, refuses an omitted or out-of-rangeNumberOfByteswith the service'sValidationExceptionwording, answersCustomKeyStoreNotFoundExceptionfor aCustomKeyStoreId, and refuses the Nitro-enclaveRecipientparameter loudly rather than answering a plaintext shape real KMS never returns there. Contributed by @iot-rocket.
Changed
- AppSync — an API's auth modes are enforced — a data-plane request satisfying none of the API's configured providers now answers
401 UnauthorizedException, as on AWS; previously an API declaringAMAZON_COGNITO_USER_POOLSserved a caller with no credentials at all. Credentials are still not verified — what is refused is the absence of any credential. Contributed by @jbschooley.
Fixed
- Persistence — a module that failed to load no longer overwrites its state — the stand-in for a module that cannot import reported empty state and
save_allwrote it over the service's file, so one bad boot silently destroyed everything that service had persisted; the stand-in now reportsNoneand the file is left alone. Contributed by @jbschooley. - ECS — a restored service relaunches its tasks — a restart restored every task
STOPPED(its container went with the process) and nothing reconciled the services, so a service reported its persistedrunningCountwhile nothing listened; ACTIVE services are now reconciled once after a restore on a daemon thread, a service that cannot relaunch is logged and skipped, and ECS joins the boot eager-load list when persisted services exist so a workload reached only through a load balancer recovers too. Contributed by @jbschooley. - Six fields accepted on write but never reported on read — Lambda's
EventSourceMappingArn(absent on create/get/list, so Terraform read no ESM tags), s3control'sListTagsForResourcetag wrapper (<member>where the model says<Tag>, unparseable by aws-sdk-go-v2), Kinesis'sKeyIdalongsideEncryptionType, RDS'sServerlessV2ScalingConfigurationandPerformanceInsightsRetentionPeriod, and Cognito'sUserAttributeUpdateSettingsand a disabledSoftwareTokenMfaConfigurationall round-trip now, each omitted when never set so an unset field does not read as drift. Contributed by @jbschooley. - ECS — a task runs on the architecture its task definition declares —
runtimePlatformwas stored and never read, so Docker chose the host's architecture and anARM64task on an x86_64 host started a container that could not execute its entrypoint; the declared architecture is now passed to Docker. Contributed by @jbschooley. - Lambda — a function runs on the architecture it declares — the container was created without a platform whatever
Architecturessaid; the declared architecture is now passed to Docker, and a cached image of the wrong architecture is re-pulled rather than failing opaquely at run. Contributed by @jbschooley. - AppSync — an anonymous operation that declares variables is parsed —
mutation($x: T!) { … }with no space after the keyword — what every SDK sends — never matched the operation pattern, so the whole document was read as one field named "mutation" and answered null with no error. Contributed by @jbschooley. - AppSync — resolver execution no longer blocks the event loop — a resolver whose data source calls back into MiniStack deadlocked the request; execution and
EvaluateCodenow run on worker threads. Contributed by @jbschooley. - Cognito —
AdminListUserAuthEventsrequires user-pool add-ons — the call answered{"AuthEvents": []}for every pool where AWS refuses withUserPoolAddOnNotEnabledException(400) unlessUserPoolAddOns.AdvancedSecurityModeis enabled; the stored add-ons now gate the operation, before user resolution, and with add-ons enabled the answer stays an empty list since events are never recorded. Contributed by @iot-rocket. - Aurora DSQL — the
ALTER TABLErefusals answer what the service answers — measured live (eu-central-1, 2026-08-30): a refusedADD CONSTRAINTdrew three invented messages where DSQL answers one,ADD COLUMNaccepted constraint clauses DSQL refuses, andALTER TABLE ASYNC ... VALIDATE CONSTRAINTover violating rows failed at submit time where DSQL fails the job —sys.jobsnow reportsfailedwith the violation asdetails. Contributed by @vivedo.