Skip to content

fix(core): report rejected client data as ActiveSync Status 6 - #248

Open
TDannhauer wants to merge 1 commit into
FRAMEWORK_6_0from
fix/activesync-invalid-data-status
Open

TDannhauer wants to merge 1 commit into
FRAMEWORK_6_0from
fix/activesync-invalid-data-status

Conversation

@TDannhauer

@TDannhauer TDannhauer commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Horde_Core_ActiveSync_Driver::changeMessage() returns ['error' => Horde_ActiveSync_Request_Sync::STATUS_INVALID] when the backend rejected the client's data (exception implementing Horde\Exception\InvalidDataThrowable), and keeps returning false for every other failure.
  • The eight identical catch (Horde_Exception $e) blocks in changeMessage() are folded into one _importFailure() helper.

Part of horde/turba#73.

Motivation

Every changeMessage() failure was reported to the device as Status 5 (server error). Clients treat that as transient and resend the item on the next Sync — forever, when the backend will never accept the data (a Turba attribute over its configured maxlength, for example). Status 6 (STATUS_INVALID) tells the client to drop the change.

Changes

  • lib/Horde/Core/ActiveSync/Driver.php
    • use Horde\Exception\InvalidDataThrowable;
    • changeMessage(): each catch (Horde_Exception $e) now does return $this->_importFailure($e, $folderid, $id); (previously _endBuffer(); return false; plus an err log). Docblock documents the new return shape.
    • _importFailure(Horde_Exception $e, $folderid, $id): ends output buffering; InvalidDataThrowable → warn ("Rejected client change for %s in folder %s: %s") and ['error' => STATUS_INVALID]; anything else → err($e->getMessage()) and false, as before.
  • test/Unit/ActiveSync/DriverChangeMessageStatusTest.php (new): contact replace and contact import with an InvalidDataThrowable → STATUS_INVALID; plain Horde_Exception → false.

Exceptions

The caught type is unchanged (Horde_Exception, the ceiling in this legacy class). The handler only classifies it: an InvalidDataThrowable is an expected, tolerable condition caused by the client (logged at warn, item rejected with a status the client understands); anything else is still a server-side failure (logged at err, retryable Status 5). No exception is swallowed that was not swallowed before.

Dependencies

Test plan

Horde_Core_ActiveSync_Driver::changeMessage() returned false for every
backend exception, which the importer reports as Status 5 (server
error). Clients treat Status 5 as transient and resend the same item on
every Sync, forever, even when the backend will never accept it.

Map exceptions implementing Horde\Exception\InvalidDataThrowable (e.g.
Turba_Exception_InvalidAttribute for a value over its configured
maxlength) to ['error' => STATUS_INVALID] and log them as a warning
naming the item; all other failures keep returning false and are logged
as errors. The eight identical catch blocks are folded into
_importFailure().

Requires the matching horde/ActiveSync change that lets the importer
honour a backend-supplied status.
Part of horde/turba#73.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant