Skip to content

feat(safePushData): detailed error reporting and result tracking - #4

Merged
metalwarrior665 merged 3 commits into
masterfrom
claude/safepushdata-logging-detail-hgw9u4
Jul 27, 2026
Merged

feat(safePushData): detailed error reporting and result tracking#4
metalwarrior665 merged 3 commits into
masterfrom
claude/safepushdata-logging-detail-hgw9u4

Conversation

@metalwarrior665

Copy link
Copy Markdown
Member

Summary

This PR significantly improves the safePushData function with better error reporting, result tracking, and more informative logging. The changes make it easier to understand what happened during the push-and-repair process and provide access to the underlying push function's return value.

Key Changes

  • Result object enhancements: Renamed fields for clarity (pushedpushedCount, droppeddroppedItems, attemptsattemptCount) and added pushResult to capture what the push function resolved to
  • Generic type support: Added generic type parameter R to PushFn and SafePushDataResult to properly type the push function's return value
  • Improved logging: Enhanced console output to report which specific fields were repaired vs. dropped, with field deduplication across items and overflow handling for pathological cases
  • Better error handling:
    • Distinguishes between repairable errors (field-level issues) and unactionable errors (item-level issues)
    • Drops items with unactionable errors immediately instead of burning attempts
    • Implements a "salvage push" for valid items when the attempt cap is reached, preventing valid data loss
    • Properly handles rejection of the salvage push itself
  • Robust state tracking:
    • Per-item placeholder path tracking that correctly follows items when earlier positions are dropped
    • Separate tracking of current-round errors vs. last-seen errors for accurate drop reporting
    • Maintains original item references for dropped item reporting

Notable Implementation Details

  • Added helper functions: collectFieldIssues(), fieldIssueLabel(), and formatFields() for structured error reporting
  • Introduced MAX_LOGGED_FIELDS constant to prevent log flooding on pathological batches
  • Shared NO_ERRORS constant to reduce allocations for items with no errors
  • The dropAt() helper centralizes position removal logic to keep parallel arrays in sync
  • Result object construction via result() helper ensures consistent return values across all exit paths
  • Comprehensive test coverage expanded from ~15 to ~50+ test cases covering edge cases like nested required fields, array element removal, JSON Pointer escaping, and salvage push scenarios

https://claude.ai/code/session_01Ek1iV9QVKioLZ3EiL4cPYc

claude added 3 commits July 24, 2026 18:36
Each failing round now reports the set of offending field paths (with the
AJV keyword) instead of just an item count, split into fields we repaired
and fields that forced a drop. The give-up log lists the fields still
failing.

The set is intentionally not a per-item breakdown: one bad field usually
appears on many items in a batch, and array indices collapse into `/tags/[]`
for the same reason. The list is capped at 20 entries with the overflow
counted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ek1iV9QVKioLZ3EiL4cPYc
…r logic

BREAKING: the result shape now names what it holds — `pushed` -> `pushedCount`,
`dropped` -> `droppedItems`, `attempts` -> `attemptCount`. `*Count` is a
number, `*Items` is an array of objects.

Whatever `pushFn` resolves to is handed back as `pushResult` (the successful
call's value; absent when every item was dropped). `PushFn<T, R>` and
`SafePushDataResult<T, R>` carry the type through.

Logic fixes found while reviewing:

- Hitting the attempt cap used to drop the *entire* remaining batch, including
  items the API never complained about — the exact data loss this wrapper
  exists to prevent. Now only the items still failing are dropped and the
  survivors get one final push of their own.
- Sibling array elements were spliced front-to-back, so the second `/tags/N`
  path pointed at a shifted array: a valid element could be deleted while the
  invalid one stayed. Errors are now applied deepest- and highest-index-first.
- A nested `required` deleted the whole parent object; it now gets the same
  placeholder treatment as a root-level one, at any depth.
- An item whose errors are all unactionable (paths it doesn't have) was
  re-pushed unchanged until the cap, burning every attempt for the rest of the
  batch. It's dropped on the spot instead.
- Give-up drops reported stale errors from an earlier round; the per-item
  errors are now reset each round, so they say why the item is failing *now*.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ek1iV9QVKioLZ3EiL4cPYc
Covers the gaps left by the previous round: additionalProperties at the root
and nested, mixed error kinds in a single round, JSON Pointer escaping on
placeholder paths, per-item state surviving a splice, dropped items reporting
the caller's original, non-object items, invalid items the API sends no errors
for, the salvage push (its pushResult, its rejection, non-schema errors from
it), maxAttempts: 1, the guard's negative cases, log label formatting, and an
end-to-end mixed batch.

Each of the five logic fixes was mutation-checked: reverting the repair
ordering, the pointer escaping, the salvage push, the no-progress drop, or the
nested `required` handling makes the corresponding tests fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ek1iV9QVKioLZ3EiL4cPYc
@metalwarrior665 metalwarrior665 changed the title Enhance safePushData with detailed error reporting and result tracking feat(safePushData): detailed error reporting and result tracking Jul 27, 2026
@metalwarrior665
metalwarrior665 merged commit 0746676 into master Jul 27, 2026
7 of 8 checks passed
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.

3 participants