Skip to content

system/sync/top returns 500 whenever an unauthenticated ActiveSync session is in the window: user and asversion are False, which the response schema rejects #91

Description

@toolonghere

Type: bug

Description

GET /api/v1/system/sync/top returns HTTP 500 whenever at least one unauthenticated
ActiveSync session falls inside the requested window. In the UI the live sync view is simply empty,
with "The server generated an invalid response."

The response itself is fine; it is the response validation that rejects it. A session that has
not authenticated yet is reported with user and asversion set to boolean False, and the schema
allows neither.

Because validation rejects the whole document, one such row blanks the entire view — the
authenticated sessions in the same response are discarded with it.

How often, and what that number means. The endpoint is only polled while the view is open in the
admin UI, so the count reflects use of that page rather than background activity. Over 30 days on
this server: 421 failed requests — 418 of them during a single working session on 26 August, and
3 more on the 28th. In other words, while the view is open it refreshes every few seconds and every
refresh fails for as long as an unauthenticated session sits in the window. From the operator's side
the page is simply never usable during that period, rather than failing occasionally.

(For completeness: the same log also holds 1 480 validation failures against
system/vhostStatus/local, but those all fall on a single day, 16 August, and have not recurred.
Different endpoint, and apparently already resolved — mentioned only so the raw log counts are not
mistaken for this issue.)

The response that fails

GET /api/v1/system/sync/top?filterEnded=20&filterUpdated=120  ->  500

Response validation failed: InvalidSchemaValue(value={'data': [
  {'addinfo': 'OK : AuthenticationRequiredException',
   'asversion': False,                    <-- boolean
   'command': 19, 'devagent': 'unknown', 'devtype': 'Outlook',
   'ip': '...', 'push': False,
   'user': False},                        <-- boolean
  {'addinfo': 'OK : Fetch : Fetch : ...',
   'asversion': '16.1',
   'devagent': 'Outlook-iOS-Android/1.0',
   'user': 'petter@rammes.se'}            <-- this row is valid
]}, schema_errors=(
  <ValidationError: 'False is not of type string'>,
  <ValidationError: 'False is not valid under any of the given schemas'>))

The two failing rows correspond to the two errors: user against type: string, and asversion
against

asversion:
  oneOf:
    - type: string
    - type: number

in res/openapi.yaml.

The record is recognisable as pre-authentication from its own addinfo:
OK : AuthenticationRequiredException, with devagent: unknown. So the values are not corrupt —
they are grommunio-sync's way of saying "not known yet", expressed as False rather than as null
or an empty string.

Where the fix belongs — we are not sure

We can see the mismatch but not which side is meant to give way, so we are describing rather than
prescribing:

  • admin-api schema could accept the absent case, e.g. nullable: true or an explicit
    - type: boolean, though the latter encodes something that is really "unknown" as a boolean.
  • admin-api serialiser could normalise falsy values to null or "" before validating.
  • grommunio-sync could report unauthenticated sessions with null or an empty string instead of
    False, if False is not deliberate there.

The last would be the cleanest as seen from outside, but we do not know whether other consumers rely
on the current shape, so it may well be the wrong place. Whichever side changes, the goal from a
user's point of view is that a pre-auth session should not blank the whole view.

Filed here because this is where the 500 is produced and where openapi.yaml lives — please move it
if grommunio-sync is the right home.

Reproducing

Have any ActiveSync client connect so that an unauthenticated attempt lands in the window (an
Outlook client reconnecting is enough), then open the live sync view, or:

curl -s -o /dev/null -w '%{http_code}\n' \
  --cookie "grommunio-auth=<jwt>" \
  'https://<host>:8443/api/v1/system/sync/top?filterEnded=20&filterUpdated=120'

The failures are logged verbatim by the API, so the simplest confirmation on an affected system is:

journalctl -u grommunio-admin-api | grep "Response validation failed" | grep -c "'user': False"

(Filtering on 'user': False matters — a plain count of "Response validation failed" on this
system also picks up an unrelated, already-resolved failure against another endpoint.)

Note on a related report

This is the same family as the type mismatch in
#83 — response/request values not matching the
declared schema — but a different instance, in a different direction, and the two are independent:
fixing either leaves the other. We mention it only so the connection is visible during triage.

Environment

grommunio-admin-api   1.20.43.mbb64403-1+64.1
grommunio-sync        2.5.2.0d70954-1
OS                    Ubuntu 24.04.4 LTS (community repo)
Scale                 5 mailboxes, 1 ActiveSync device

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions