Map HistorianGateway AGGREGATE_NOT_SUPPORTED_FOR_TAG (FailedPrecondition) to BadAggregateNotSupported without counting health #900
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follow-up to #897 (fixed up front for Boolean nodes in
ee39c169) and the gateway side historiangw#135 (merged to historiangwmain@a220ec0).What the gateway now sends. When AVEVA refuses an aggregate retrieval mode for the tag (AVEVA 2023 R2: TimeWeightedAverage / MinimumWithTime / MaximumWithTime / Integral / Slope on a discrete or string tag; native CustomError 85 at
StartQuery),ReadAggregatefails with:FailedPrecondition,Status.Detail=HistorianAggregateNotSupportedException;google.rpc.ErrorInfoingrpc-status-details-bin: reasonAGGREGATE_NOT_SUPPORTED_FOR_TAG, domainhistorian_gateway.v1, metadataretrieval_mode(e.g.RETRIEVAL_MODE_TIME_WEIGHTED_AVERAGE) andnative_error_code(85).A genuine historian fault stays
Internalwith no ErrorInfo. Live, read-only on wonder-sql-vd03 (2026-11-13):SysPulseTWA/Integral gave the new status;SysTimeSecTWA/Integral andSysPulseCyclic were still served.Ask (OtOpcUa). In
GatewayHistorianDataSource(native processed read,ReadProcessed…catch aroundRecordReadFailure(ex)), recognise that refusal and:BadAggregateNotSupported(Part 11 §6.5.4), notBadHistoryOperationUnsupported;RecordReadFailure/ count it in the historian health snapshot (it is the tag's configuration, not a backend failure) and do not treat it as transport.This covers the residual #897 case: a node declared numeric whose AVEVA tag is actually discrete still reaches AVEVA.
How to detect it.
HistorianGatewayException.ErrorReason == HistorianGatewayErrorReasons.AggregateNotSupportedForTag(alsoErrorDomain,ErrorMetadata; contract enumHistorianErrorReason).ex.StatusCode == FailedPreconditionand the innerRpcException'sGetRpcStatus()?.GetDetail<Google.Rpc.ErrorInfo>()?.Reason == "AGGREGATE_NOT_SUPPORTED_FOR_TAG"(needsGrpc.StatusProto). Match on the reason, not on FailedPrecondition alone: the gateway also uses FailedPrecondition for other things (live writes disabled, a historian-side FailedPrecondition passed through).Compatibility. An older gateway still sends
Internalfor this case, so the existing handling must stay. Don't bump theZB.MOM.WW.HistorianGateway.Clientpin until 1.1.0 is on the feed.Tests to add. Extend
DiscreteTagTimeWeightedWireTests(AVEVA-shaped fake gateway): a Double/Int node whose fake gateway answers FailedPrecondition + ErrorInfo →BadAggregateNotSupported, 0 health failures. Positive control: anInternalanswer still counts as a failure. Re-run the AVEVA live gate against a gateway at or aftera220ec0.Fixed in
efaf3435onmaster.What changed. If the gateway refuses the aggregate with FailedPrecondition and the
google.rpc.ErrorInforeasonAGGREGATE_NOT_SUPPORTED_FOR_TAG(domainhistorian_gateway.v1), the native processed read inGatewayHistorianDataSource(ReadNativeAsync) now throwsHistoryAggregateNotSupportedException. The node getsBadAggregateNotSupported.RecordReadFailureis not called and the read is not treated as transport. Nothing else changes: any other FailedPrecondition, and everyInternal(which is what an older gateway sends for this case), still getsBadHistoryOperationUnsupportedand counts as a failure.Detection (one place:
GatewayErrorReasons). The Client pin stays at 1.0.0. Client 1.0.0'sMapRpcExceptionkeeps the gateway'sRpcException, trailers included, as theInnerExceptionof theHistorianGatewayExceptionit throws. SoReasonOfwalks the exception chain and readsGetRpcStatus()?.GetDetail<Google.Rpc.ErrorInfo>(). This needsGrpc.StatusProto2.76.0, added through central package management. It comes from nuget.org, matches the Grpc.Core.Api version, and pulls in Google.Api.CommonProtos 2.16.0, which accepts Google.Protobuf 3.34.1. A malformed trailer or a different domain counts as no reason. When Client 1.1.0 is on the feed,ReasonOfbecomes(ex as HistorianGatewayException)?.ErrorReason(one line) and the StatusProto reference can be removed. The code comment says the same.Tests.
GatewayAggregateNotSupportedWireTests(new): an in-process gRPC gateway sends the real status plus the ErrorInfo shape (copied from historiangwHistorianRpcFaults.ToRpcException). The test reads through the published Client 1.0.0 via the production adapter. TimeAverage and Total giveBadAggregateNotSupportedand 0 health failures. These controls are rethrown, are not IOException, and count as failures: Internal; FailedPrecondition with no ErrorInfo; another reason; another domain; the right reason on Internal. A positive control is served.DiscreteTagTimeWeightedWireTests: over a real SDK session, a Double node and an Int32 node on the discrete tag giveBadAggregateNotSupportedand 0 failures. Control: the older gateway'sInternalanswer keeps its status and counts.AvevaGatewayAggregateRefusalLiveGateTests: an opt-in, read-only live gate (HISTGW_GATEWAY_ENDPOINT/_APIKEY+OTOPCUA_AVEVA_GATE_900=true).Live gate, read-only (2026-11-13). I ran a private HistorianGateway container built from
a220ec0(API-key auth disabled, live writes off, removed afterwards) against wonder-sql-vd03:SysPulse, TimeAverage and Total: BadAggregateNotSupported, health failures unchanged at 0.SysTimeSecTimeAverage: Good, 2 rows.SysPulseAverage: served.The gateway saw only
ReadAggregate,ReadRawandGetTagMetadata. Nothing was written and no tags were created. The rig builds no provisioner or recorder. One unplanned negative control: a stale build with the catch disabled answered the same live readBadHistoryOperationUnsupported.docs/Historian.md(Aggregates by node DataType) is updated. Deployment: vd03 and QA need both this OtOpcUa build and a HistorianGateway at or aftera220ec0before the behaviour shows. Against today's deployed gateways the answer is unchanged.Contracts + Client 1.1.0 published to the Gitea feed on 2026-11-13: release commit
6365f34(tagv1.1.0) on historiangw main. Verified by restoring from the feed into a throwaway project: the SHA256 matches the packed artifacts andHistorianGatewayErrorReasons.AggregateNotSupportedForTagcompiles. Client 1.1.0 depends onGrpc.StatusProto2.76.0. OtOpcUa still pins 1.0.0; switching to 1.1.0 is the one-lineReasonOfchange noted in lmxopcua#900.The HistorianGateway side of this is now deployed on DEV and QA (2026-11-13, historiangw
6365f34, historiangw#135). It runs on vd03, vq04 and vq03, soc9640f5c's #900 mapping is now reachable on both tiers.On all three boxes,
ReadAggregateTWA on the discreteSysPulse, called with OtOpcUa's key, now returnsFailedPreconditionwith ErrorInfo reasonAGGREGATE_NOT_SUPPORTED_FOR_TAG(domainhistorian_gateway.v1) ingrpc-status-details-bin. The previous builds returnedInternal. OtOpcUa's historian probe kept running through each ~6.5 s swap, and:9000/health/readystayed 200.Record: historiangw
docs/deploy/2026-11-13-vd03-qa-6365f34-record.md.Moved to HistorianGateway Client/Contracts 1.1.0 on master
76e73e7d(historiangw#135, release6365f34).GatewayErrorReasonsnow reads Client 1.1.0's typedHistorianGatewayException.StatusCode/ErrorReason/ErrorDomain(constants fromHistorianGatewayErrorReasons). It no longer parsesgrpc-status-details-binitself, and the directGrpc.StatusProtopin and reference are gone (the client brings it in). There is no trailer fallback: the published client maps everyRpcExceptionto aHistorianGatewayException.FailedPrecondition+AGGREGATE_NOT_SUPPORTED_FOR_TAG(domainhistorian_gateway.v1) givesBadAggregateNotSupported, and every other shape keeps its handling.GatewayErrorReasonsTests(11), whose exceptions carry the reason only on the typed properties. The wire tests andDiscreteTagTimeWeightedWireTestspass through the published 1.1.0 client. Four mutations were each caught: status check dropped, domain check dropped, never-refusal, and a revert to the old trailer implementation.Not deployed. It ships with the next deploy after
47f0b98c.Deployed to DEV vd03 and the QA pair vq03/vq04 on 2026-11-13. The build is master
76e73e7d: HistorianGateway Client/Contracts 1.1.0 and the typedHistorianGatewayExceptionreason. Record:docs/deploy/2026-11-13-vd03-qa-to-76e73e7d.md(5baf05f6).deps.jsonon all three nodes showsZB.MOM.WW.HistorianGateway.Client/1.1.0. HG on both tiers is6365f34(the 1.1.0 server).:5220/metrics,HistorianStatus/Probeok went 494 (12:27:17Z) → 504 (12:31:52Z) → 536 (12:47:45Z). The boot log hasHistorian gateway probe: the gateway is reachable.The other counters did not move: BrowseTagNames 1, ReadRaw 1, ReadAggregate ok 1 / error 2. There is noEnsureTags,AddTagExtendedProperties,WriteLiveValues,AddHistoricalValuesorSendEvent(s)series.AGGREGATE_NOT_SUPPORTED_FOR_TAG→BadAggregateNotSupportedmapping. Neither tier has historized tags. The mapping is covered byGatewayErrorReasonsTestsand the wire tests.Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi