instructure/canvas-lms · error

error.message

Error message

error.message

What it means

rescue_content_service_error handles exceptions bubbling out of the content-service client (used by wiki page create/show/update). It logs an ErrorReport tagged 'content_service_client_error' (with the upstream service's error messages) and renders {"error": error.message, "error_report_id": ...} with HTTP 503 Service Unavailable. A 503 here means Canvas could not complete the operation because the external content service (e.g. Horizon block content processing) is unavailable or returned errors — the problem is upstream, not with the wiki page itself.

Solutions

  1. Look up error_report_id from the response in Canvas admin Error Reports — the stored message and service_errors detail what the upstream service reported.
  2. Check the content service's health/status endpoint and its logs; retry the page operation once the service recovers.
  3. Verify the content service URL/credentials configuration in this Canvas environment after any deploy or config change.
  4. If the service rejects specific page content, simplify or remove the offending HTML block and retry the save.

Example fix

// before: assuming page save failure means invalid page data
if (res.status === 503) alert('Invalid page content');
// after: treat 503 as upstream outage and surface the report id
if (res.status === 503) {
  const body = await res.json();
  showError(`Content service temporarily unavailable (report ${body.error_report_id}). Try again later.`);
}
Defensive patterns

Strategy: retry

Validate before calling

// before saving a page in a horizon_block_content_editor? account
const serviceHealthy = await fetch(contentServiceHealthUrl).then(r => r.ok).catch(() => false);
if (!serviceHealthy) queueSaveForRetry(page);

Type guard

function isContentServiceError(e) {
  return e instanceof Error && Array.isArray(e.service_errors);
}

Try / catch

try {
  const page = await api.createWikiPage(payload);
} catch (e) {
  if (isContentServiceError(e)) {
    // e.name === 'content_service_client_error' in ErrorReports; HTTP 503 with error_report_id
    await retryWithBackoff(() => api.createWikiPage(payload), { maxAttempts: 3 });
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Creating, showing, or updating a wiki page in an account with the horizon block content editor enabled (create_external_content_ref), where the call to the external content service raises an error carrying .service_errors — service outage, network failure, timeout, or the service rejecting the submitted content.

Common situations: Horizon/content-service deployment down or being upgraded; network/firewall blocking Canvas→service traffic; service returning 4xx/5xx because the page HTML contains unsupported content; environment misconfiguration of the content service URL or credentials after a deploy.


AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15). Data as JSON: /api/errors/6f3bdd56cab76d47. Report an issue: GitHub.

Appendix: source

Thrown at app/controllers/wiki_pages_api_controller.rb:947

  private

  def ai_alt_text_params_valid?
    return false if params[:attachment_id].blank?

    true
  end

  def rescue_unparsable_content(error)
    @page.errors.add(:body, error.message) if @page.present?

    render json: @page&.errors || {}, status: :bad_request
  end

  def rescue_content_service_error(error)
    error_report = ErrorReport.log_error(
      "content_service_client_error",
      { message: error.message, service_errors: error.service_errors }
    )
    render json: { error: error.message, error_report_id: error_report.id }, status: :service_unavailable
  end

  def create_external_content_ref
    return unless @context.account.horizon_block_content_editor?

    @page.create_block_editor_data(user_uuid: @current_user.uuid, data: @block_editor_data)
  end

  def update_external_content_ref
    return unless @context.account.horizon_block_content_editor?

    @page.update_block_editor_data(user_uuid: @current_user.uuid, data: @block_editor_data)
  end

  def extract_block_editor_data
    return unless params[:wiki_page] && @context.account.horizon_block_content_editor?

View on GitHub (pinned to 1c9f0bb801)