Skip to content

Retry Discord API 5xx errors and handle non-JSON error bodies#87

Merged
localden merged 1 commit intomainfrom
den/discord-retry-5xx
Mar 23, 2026
Merged

Retry Discord API 5xx errors and handle non-JSON error bodies#87
localden merged 1 commit intomainfrom
den/discord-retry-5xx

Conversation

@localden
Copy link
Contributor

Summary

  • Add tryParseJson helper so Cloudflare plain-text error bodies (e.g. upstream connect error..., error code: 1015) don't crash response.json() in the 429/error paths
  • Retry 5xx responses with exponential backoff + jitter, same as the existing 429 handling
  • Fall back to raw status + body text in error messages when the response isn't valid JSON

Test plan

  • pulumi preview succeeds against the Discord provider
  • Deploy workflow passes (previously flaked on transient 502/504 from Discord's Cloudflare edge)

Cloudflare edge errors (5xx, edge-level 429s) return plain-text bodies
like "upstream connect error..." or "error code: 1015" that crash a
naive response.json() call. Add a tryParseJson helper and use it for
all error paths so we surface the actual HTTP status/body instead of a
JSON parse exception.

Also add exponential backoff retry for 5xx responses, matching the
existing 429 retry behavior.

:house: Remote-Dev: homespace
@localden localden requested a review from a team as a code owner March 23, 2026 22:51
@github-actions
Copy link

Pulumi Preview

Click to expand preview output
Previewing update (prod):
  pulumi:pulumi:Stack: (same)
    [urn=urn:pulumi:prod::mcp-access::pulumi:pulumi:Stack::mcp-access-prod]
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760670395039755]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-maintainers]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760673498959945]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-administrators]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760656226680903]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-moderators]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760698316652557]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-kotlin-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760775705493770]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-rust-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760701344813136]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-swift-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760687444758623]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-sdk-maintainers]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760684643221556]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-use-mcp-maintainers]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760714607071465]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-typescript-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760676367597740]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-inspector-maintainers]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760804134752443]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-go-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760695821041767]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-java-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760690611720404]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-registry-maintainers]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760693585215508]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-agents-ig]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760759024750644]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-server-identity-wg]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch*/(token, endpoint, options = {}, maxRetries = 10) {
                let lastError;
            ...
                    });
                    if (response.status === 429) {
          -             const body = (await response.json());
          +             const text = await response.text();
          +             const body = tryParseJson(text);
          +             const retryAfterSec = body?.retry_after ?? 1;
                        // Linearly increasing jitter de-syncs the thundering herd when many
                        // resources refresh in parallel and all receive the same retry_after.
                        const jitterMs = Math.random() * 1000 * (attempt + 1);
          -             const retryAfterMs = Math.ceil(body.retry_after * 1000) + jitterMs;
          -             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${body.retry_after}s, global=${body.global})`);
          +             const retryAfterMs = Math.ceil(retryAfterSec * 1000) + jitterMs;
          +             lastError = new Error(`Discord API rate limited on ${endpoint} (retry_after=${retryAfterSec}s, global=${body?.global ?? false})`);
                        if (attempt < maxRetries) {
                            await sleep(retryAfterMs);
            ...
                        throw lastError;
                    }
          +         if (response.status >= 500 && response.status < 600) {
          +             const text = await response.text();
          +             lastError = new Error(`Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
          +             if (attempt < maxRetries) {
          +                 await sleep(2 ** attempt * 500 + Math.random() * 1000);
          +                 continue;
          +             }
          +             throw lastError;
          +         }
                    if (!response.ok) {
          -             const error = (await response.json());
          -             throw new Error(`Discord API error: ${error.message} (code: ${error.code})`);
          +             const text = await response.text();
          +             const error = tryParseJson(text);
          +             throw new Error(error
          +                 ? `Discord API error: ${error.message} (code: ${error.code})`
          +                 : `Discord API ${response.status} on ${endpoint}: ${text.slice(0, 200)}`);
                    }
                    // Handle 204 No Content
            ...
    ~ pulumi-nodejs:dynamic:Resource: (update)
        [id=1460760711796887821]
        [urn=urn:pulumi:prod::mcp-access::pulumi-nodejs:dynamic:Resource::discord-role-php-sdk]
      ~ __provider: 
            exports.handler = __f0;
            var __provider = {create: __f1, read: __f2, update: __f3, delete: __f4};
          + function __tryParseJson(__0) {
          +   return (function() {
          +     with({ tryParseJson: __tryParseJson, this: undefined, arguments: undefined }) {
          + return function /*tryParseJson*/(text) {
          +     try {
          +         return JSON.parse(text);
          +     }
          +     catch {
          +         return undefined;
          +     }
          + };
          +     }
          +   }).apply(undefined, undefined).apply(this, arguments);
          + }
            function __sleep(__0) {
              return (function() {
            ...
            function __discordFetch(__0, __1) {
              return (function() {
          -     with({ DISCORD_API_BASE: "https://discord.com/api/v10", sleep: __sleep, discordFetch: __discordFetch, this: undefined, arguments: undefined }) {
          +     with({ DISCORD_API_BASE: "https://discord.com/api/v10", tryParseJson: __tryParseJson, sleep: __sleep, discordFetch: __discordFetch, this: undefine...
            return async function /*discordFetch

... (truncated)

@localden
Copy link
Contributor Author

Direct push to main given that it's a low-risk change that fixes the transient Discord issues.

@localden localden merged commit 40c29e3 into main Mar 23, 2026
5 checks passed
@localden localden deleted the den/discord-retry-5xx branch March 23, 2026 22:53
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