gitroomhq/postiz-app · error · HttpException

Unexpected error

Error message

Unexpected error

What it means

triggerIntegrationTool wraps tool invocation in a while(true) loop with a 10-second timer between attempts; if every attempt falls through the retry branches without producing a success or early throw, the loop exits to a catch-all 500 'Unexpected error'. It signals an unclassifiable provider-side failure that persisted through all retries.

Source

Thrown at apps/backend/src/public-api/routes/v1/public.integrations.controller.ts:631

            throw new HttpException(
              { msg: 'Channel disconnected due to expired token' },
              401
            );
          }

          const { accessToken } = data;

          if (accessToken) {
            getIntegration.token = accessToken;

            if (integrationProvider.refreshWait) {
              await timer(10000);
            }

            continue;
          }
        }
        throw new HttpException({ msg: 'Unexpected error' }, 500);
      }
    }
  }
}

View on GitHub (pinned to 0f1647f749)

Solutions

  1. Inspect the backend logs at the time of the 500 to see the underlying provider exception and response payload
  2. Test the same tool invocation from the UI to isolate whether it is specific to the public API call's arguments
  3. Verify the arguments match the tool's expected schema (many tools fail silently on malformed input)
  4. If the channel's API changed, update Postiz to a version with the fixed provider implementation

Example fix

// before
const res = await triggerTool(id, method, args); // throws 500 'Unexpected error'

// after
// capture and log the tool response/args to identify the provider-level failure
try {
  const res = await triggerTool(id, method, args);
} catch (e) {
  if (e.status === 500) {
    logger.error('tool failed', { id, method, args, body: e.response?.body });
    // inspect backend logs for the underlying provider error
  }
  throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

if (!body?.methodName || typeof body.methodName !== 'string') throw new Error('methodName required');
// validate args against the tool's documented schema before calling

Type guard

const isUnexpectedToolError = (e: unknown): boolean =>
  (e as any)?.status === 500 && (e as any)?.response?.msg === 'Unexpected error';

Try / catch

try {
  await triggerTool(id, method, args);
} catch (e: any) {
  if (e?.status === 500) {
    await sleep(5000);
    return triggerTool(id, method, args); // single client-side retry; server already retried internally
  }
  throw e;
}

Prevention

When it happens

Trigger: POST to triggerIntegrationTool where the provider method keeps returning a falsy/unknown result shape (neither success nor a recognized retry condition) until the internal retry budget is exhausted; also any unexpected exception from the dynamic integrationProvider[body.methodName] call that is not caught by the token-refresh branch.

Common situations: Provider API returning an unexpected response schema (breaking change on the channel's API); provider method throwing a non-OAuth error repeatedly; network-level failures to the channel endpoint; invoking a tool with malformed arguments that the provider silently fails on.

Related errors


AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27). Data as JSON: /api/errors/42219c060b30109c. Report an issue: GitHub.