← back to Goldleafwallpaper
scripts/ig-poster/classify-error.js
49 lines
'use strict';
/**
* classify-error.js — classify a failed IG Graph publish error message.
*
* WHY THIS EXISTS (TK-11880 grooming cycle 2, 2026-09-17):
* Meta's Graph API stamps MANY non-auth failures with `type:"OAuthException"`.
* The poster's old inline test keyed the "token expired — re-auth" alert off the
* bare substring `OAuth`, so a MEDIA-FETCH rejection (code 9004 / subcode 2207052,
* "The media could not be fetched from this URI") was misclassified as a dead token
* and fired a false re-auth alert — on a token that meta-token-canary independently
* reads as HEALTHY (verified 2026-09-17). That is the CLAUDE.md TK-11431 "a check
* reported the wrong cause" class: it would send someone to rotate a healthy
* credential while the REAL problem (an image URL IG can't fetch/accept) stays hidden.
*
* The fix: recognize the media-error signature explicitly and EXCLUDE it from the
* auth test, while keeping genuine expiry detection (Meta always carries code 190 +
* a canonical "Session has expired" / "access token" phrase on a real expiry).
*
* Pure + side-effect free so it can be unit-tested without running the poster
* (the poster would otherwise attempt a live post). Ship the testability seam.
*/
// IG media-fetch / media-type rejections. NOT a token problem — the token is fine;
// IG could not fetch or accept the image URL (dimensions, format, or transform params).
const MEDIA_ERR_RE =
/"code":\s*9004|"error_subcode":\s*2207052|media could not be fetched|Only photo or video can be accepted/i;
// Genuine access-token failures. Meta emits code 190 (+ subcodes 458/463/467/492)
// with a canonical "Session has expired" / "access token" phrase on a real expiry.
// Deliberately does NOT match the bare type string "OAuthException" alone, because
// media (9004) and rate-limit (4/17/32/613) errors also carry that type.
const AUTH_ERR_RE =
/"code":\s*190|"error_subcode":\s*(?:458|463|467|492)|access token|session has expired|not a valid access token|token is invalid/i;
/**
* @param {string} msg the error message (typically the JSON body Meta returned)
* @returns {{isMediaErr:boolean, isAuthErr:boolean}}
* isAuthErr is only true when it is NOT a media error, so a code-9004 rejection
* can never route to the re-auth alert.
*/
function classifyPostError(msg) {
const s = String(msg == null ? '' : msg);
const isMediaErr = MEDIA_ERR_RE.test(s);
const isAuthErr = !isMediaErr && AUTH_ERR_RE.test(s);
return { isMediaErr, isAuthErr };
}
module.exports = { classifyPostError, MEDIA_ERR_RE, AUTH_ERR_RE };