fix(dexcomshare): surface auth failures, handle modern response shape, harden catch paths - #55
Open
csinghaus-sfdc wants to merge 1 commit into
Conversation
…, harden catch paths Five related bugs in lib/sources/dexcomshare.js conspired to mask Dexcom Share authentication failures and break G7-era accounts. Symptoms in the field: silent "0 entries" polling for valid credentials, misleading "InvalidArgument: cannot deserialize java.util.UUID from Object value" 500 responses from Dexcom for valid-but-misframed login flows, and unhandled ReferenceError / TypeError crashes on any non-HTTP error path. 1. authFromCredentials swallowed errors by returning the AxiosError as a resolved value. The state machine treated that as a successful auth, then passed the Error object downstream where sessionFromAuth serialized it into the request body. Dexcom rejected that with the confusing UUID-deserialization 500, hiding the real upstream failure (e.g., AccountPasswordInvalid). Fix: re-reject so the state machine's AUTHENTICATION_ERROR path runs. 2. Dexcom's AuthenticatePublisherAccount endpoint now returns a JSON object containing accountId for newer (G7-era) accounts instead of a bare UUID string. The plugin assumed the bare-string shape and sent the wrapper object as accountId on the next request. Fix: in authFromCredentials normalize to the bare UUID; in sessionFromAuth accept either shape defensively. 3. catch blocks in sessionFromAuth and dataFromSesssion referenced `error.response.data` where the variable in scope is `err`. Any time the catch block was actually entered it would throw ReferenceError instead of returning the structured failure object. Fix: use the right identifier. 4. err.response was dereferenced without an existence check, so the catch path itself crashed with TypeError on any non-HTTP error (DNS failure, ECONNRESET, TLS handshake fail, request timeout). Fix: defensive optional access. 5. transformGlucose called data.map() on whatever it received, which could be a non-array failure object (especially given the error-swallowing in bug 1). TypeError instead of an empty-entries return. Fix: guard with Array.isArray. The new catch-block log lines are also more useful for diagnostics: they print status + body + the AxiosError's `message` field together on a single line. Validated against a live Dexcom G7 patient account on Heroku; the patched plugin correctly surfaces AccountPasswordInvalid where upstream silently looped on broken state.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes five related bugs in
lib/sources/dexcomshare.jsthat together cause Dexcom Share authentication failures to never surface, produce misleading downstream 500s, and crash the catch paths on any non-HTTP error.Field symptom (especially common for G7 accounts): the plugin reports
RUNNING 0 failures 0indefinitely and never stores new entries, even though logs claimtype: 'AUTHENTICATED'. The actual underlying error from Dexcom is being swallowed.Bugs fixed
authFromCredentialsreturns the error object as a resolved value. The state machine treats it as a successful authentication and passes theErrorobject intosessionFromAuthasaccountId. Dexcom then responds with500 InvalidArgument: cannot deserialize java.util.UUID from Object value, hiding the real upstream cause (typicallyAccountPasswordInvalid). Fixed by re-rejecting the promise so the state machine runs itsAUTHENTICATION_ERRORpath.{accountId: "<uuid>"}fromAuthenticatePublisherAccountrather than a bare UUID string. The plugin sent the wrapper object as the next request'saccountId. Fixed by normalizing to the bare UUID inauthFromCredentialsand accepting either shape defensively insessionFromAuth.error.response.datatypo in two catch blocks (sessionFromAuth,dataFromSesssion). The variable in scope iserr. Catch block crashes withReferenceErrorwhenever entered. Fixed by using the right identifier.err.responsedereferenced without an existence check. Crashes the catch path withTypeErroron any non-HTTP error (DNS, ECONNRESET, TLS, timeout). Fixed with defensive access.transformGlucosedoesdata.map()on whatever it receives, including non-array failure objects (especially with bug experimental capture mode #1 papering over auth failures). Fixed by guarding withArray.isArray.The new error-log format also surfaces the Dexcom response body + the AxiosError message on a single line, which made diagnosing this PR's root cause take minutes instead of hours.
Testing
Validated against a live Dexcom G7 patient account on Heroku. Before the patch, the plugin looped silently with stale data and confusing logs. After the patch, the plugin surfaces
AccountPasswordInvaliddirectly from Dexcom's response — a real auth issue the user can act on.Notes
dataFromSesssion's catch (nowPromise.rejectinstead of a wrapped object) is consistent with the other two paths and aligns with what the state machine seems to expect (it already handles rejection via itsonErrortransitions).Closes any open issue tracking the "0 entries forever" behavior or the cryptic UUID-deserialization 500s.