opf/openproject · error · Import::JiraClient::ConnectionError
Connection to Jira server timed out: %{message}
Error message
Connection to Jira server timed out: %{message} What it means
In download_attachment, Timeout::Error (including Net::OpenTimeout/Net::ReadTimeout subclasses) is wrapped into Import::JiraClient::ConnectionError with this message. The client uses the frozen HTTP_OPTIONS = { open_timeout: 30, read_timeout: 30 }, so exceeding either limit while connecting to or streaming a Jira attachment raises; the original timeout detail is in %{message}.
Source
Thrown at app/services/import/jira_client.rb:275
tempfile = Tempfile.create(filename, binmode: true)
response.read_body do |chunk|
tempfile.write chunk
end
yield tempfile
else
status = response.code.to_i
raise ApiError.new(I18n.t("admin.jira.client.api_error", status:), status:, response_body: response.body)
end
end
nil
rescue SsrfFilter::PrivateIPAddress
raise SsrfError, I18n.t("admin.jira.client.ssrf_blocked")
rescue SsrfFilter::Error => e
raise ConnectionError, I18n.t("admin.jira.client.connection_error", message: e.message)
rescue OpenSSL::SSL::SSLError => e
raise ConnectionError, I18n.t("admin.jira.client.ssl_error", message: e.message)
rescue Timeout::Error => e
raise ConnectionError, I18n.t("admin.jira.client.connection_timeout", message: e.message)
ensure
File.unlink(tempfile) if tempfile
end
private
def get(path, params: {})
response = get_response(path, params:)
handle_response(response)
end
def get_response(path, params: {})
OpenProject::SsrfProtection.get(
"#{@url}#{path}",
headers: @headers,
params:,
http_options: HTTP_OPTIONS
)View on GitHub (pinned to d9742c43f3)
Solutions
- Measure actual connectivity from the OpenProject host: curl -o /dev/null -w 'connect=%{time_connect} total=%{time_total}' '<attachment-url>'
- If transfers legitimately exceed 30s, raise the timeouts (HTTP_OPTIONS is a frozen constant — patch it via an initializer/upstream change) or reduce attachment sizes
- Retry the operation: transient congestion is the most common cause and a second attempt often succeeds
- For recurring stalls, check path MTU/VPN encapsulation and Jira-side GC pauses
Example fix
# before
client.download_attachment(content_url, filename) { |tf| attach(tf) }
# after — retry transient timeouts with backoff
attempts = 0
begin
attempts += 1
client.download_attachment(content_url, filename) { |tf| attach(tf) }
rescue Import::JiraClient::ConnectionError => e
raise if attempts >= 3 || !e.message.include?("timed out")
sleep(2**attempts)
retry
end Defensive patterns
Strategy: retry
Try / catch
attempts = 0
begin
attempts += 1
client.download_attachment(content_url, filename) { |tf| attach(tf) }
rescue Import::JiraClient::ConnectionError => e
raise if attempts >= 3 || !e.message.include?("timed out")
sleep(2**attempts)
retry
end Prevention
- Bound retries (2-3) with exponential backoff; a hard 30s timeout repeated forever just stalls the import
- Record which attachments failed so a later pass can re-fetch only those
- Baseline the attachment fetch time from the OpenProject host before starting a large import
When it happens
Trigger: client.download_attachment where the TCP/TLS connect takes over 30s (typically a firewall silently dropping packets so the connect hangs), or the streamed attachment body stalls/pushes data slower than the 30s read timeout allows (large attachments on a slow or throttled link, paused Jira node).
Common situations: Containerized OpenProject with no route to the Jira network (packets blackholed instead of rejected); VPN/MTU problems that stall mid-transfer of large attachments; bulk imports hitting an overloaded Jira so responses trickle; nightly backup windows slowing the Jira host.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Failed to connect to Jira server: %{message}
- SSL error connecting to Jira server: %{message}
- Connection blocked: the Jira host resolves to a private IP a
- Failed to parse Jira API response: %{message}
- LDAP-Error: %{error_message}
AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21).
Data as JSON: /api/errors/9c5a94edafd61a61.
Report an issue: GitHub.