opf/openproject · error · Import::JiraClient::ConnectionError
SSL error connecting to Jira server: %{message}
Error message
SSL error connecting to Jira server: %{message} What it means
During download_attachment, OpenSSL::SSL::SSLError from the TLS handshake with the attachment host is wrapped into Import::JiraClient::ConnectionError with this message. Net::HTTP raises it when certificate verification fails (self-signed/untrusted CA, incomplete chain, hostname mismatch, expired certificate) or when TLS negotiation itself breaks; the OpenSSL detail stays in %{message}.
Source
Thrown at app/services/import/jira_client.rb:273
case response
when Net::HTTPSuccess
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:,View on GitHub (pinned to d9742c43f3)
Solutions
- Inspect the certificate chain from the OpenProject host: openssl s_client -connect jira.host:443 -servername jira.host </dev/null and check the verify result
- Fix the server side first: complete chain (leaf + intermediates), hostname matching, certificate not expired
- For internal CAs, add the CA certificate to the OpenProject container/system trust store (Debian: copy to /usr/local/share/ca-certificates/ and run update-ca-certificates; also set NODE_EXTRA_CA_CERTS for Node-based tooling)
- Never work around it by disabling certificate verification — that removes the SSRF/TLS protections this client is built around
Example fix
# before — Jira uses an internal CA; downloads fail with # SSL error connecting to Jira server: ... certificate verify failed # after — trust the internal CA inside the OpenProject image # Dockerfile: # COPY jira-internal-ca.crt /usr/local/share/ca-certificates/ # RUN update-ca-certificates # docker-compose.yml (for Node-based parts of the stack): environment: NODE_EXTRA_CA_CERTS: /usr/local/share/ca-certificates/jira-internal.crt
Defensive patterns
Strategy: try-catch
Try / catch
begin
client.download_attachment(content_url, filename) { |tf| attach(tf) }
rescue Import::JiraClient::ConnectionError => e
if e.message.start_with?("SSL error")
report_cert_problem(host: URI.parse(content_url).host, detail: e.message)
end
raise
end Prevention
- Manage the internal CA in the OpenProject image as configuration (COPY + update-ca-certificates), not ad-hoc
- Monitor certificate expiry on the Jira/proxy side so renewals happen before imports fail
- Run openssl s_client against the Jira host as part of environment bring-up checks
When it happens
Trigger: client.download_attachment fetching an https attachment URL where the server presents a self-signed or internal-CA certificate, is missing intermediate certificates, has a CN/SAN not matching the host, has an expired certificate, or only supports TLS versions the client rejects.
Common situations: Self-hosted Jira behind a reverse proxy with an internal PKI certificate not trusted by the OpenProject container's CA store; admins renewing certs but forgetting intermediates; lab environments using self-signed certs; cert renewed but proxy still serving the old one.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Failed to connect to Jira server: %{message}
- Connection to Jira server timed out: %{message}
- Connection blocked: the Jira host resolves to a private IP a
- LDAP-Error: %{error_message}
- Failed to parse Jira API response: %{message}
AI-assisted analysis of opf/openproject@d9742c43f3 (2026-08-21).
Data as JSON: /api/errors/0aaa510f1681f845.
Report an issue: GitHub.