01Quick reference

-14Credentials rejected. Wrong username/password (most common), or auth succeeds but the user isn't in the SSL-VPN group / Host Check fails. → §03
-8Source IP temporarily blocked. Too many failed logins tripped the SSL-VPN lockout — usually a string of -14s. → §04
-20199Can't establish the connection. Server unreachable or a client-side stack/Internet-Options problem. → §05
-5029TLS version mismatch. Fails around 31%; client and FortiGate have no common TLS version. → §06

error code = the layer that failed → -14 auth · -8 lockout · -20199 reachability · -5029 TLS

02Read the failure like a pro

Two signals turn a vague error into a diagnosis before you change anything:

  • The percentage it dies at. A connection that fails at a low, fixed percentage (e.g. ~31% for -5029) is failing during TLS setup — before authentication. A failure after the credential prompt is an auth/authorization problem (-14/-8).
  • Two logs, not one. Check the FortiClient log (Settings → Logs, or %LocalAppData%\FortiClient\logs) for the client's view, and the FortiGate SSL-VPN / event log for the server's. They rarely lie in the same direction — the truth is where they disagree.

03Error -14: credentials rejected

Cause. The FortiGate refused the login. Ninety percent of the time it's a plain wrong username or password; the rest is "authentication worked but you're not authorized" — the account isn't in the group bound to the SSL-VPN portal, or Host Check on the portal failed.

On the client: retype the password (watch Caps Lock and any domain\user or user@realm format your org requires); confirm the gateway URL and port; try a known-good account to isolate user-vs-config.

On the FortiGate: confirm the user is in the group referenced by the SSL-VPN policy/portal, and watch the auth daemon decide in real time:

diagnose debug reset
diagnose debug application fnbamd -1        # authentication daemon: user, group, 2FA
diagnose debug enable
# … reproduce the FortiClient login now …
diagnose debug disable
diagnose debug reset
fnbamd: ... authenticate 'jdoe' ...
fnbamd: ... auth failed: 'Invalid password'      <- it really is the password
# (or) auth ok but no matching group → fix group membership / portal mapping, not the password

04Error -8: your IP is temporarily blocked

Cause. A brute-force guard. After several failed logins (often a run of -14s), the FortiGate temporarily blocks the source IP. Correct credentials will still fail until the block timer expires — which is exactly why -8 feels baffling right after you "fixed" the password.

On the client: stop retrying, wait out the block (often ~60s to a few minutes), then try once with confirmed-correct credentials.

On the FortiGate: the thresholds live in the SSL-VPN settings — raise them if legitimate users are getting caught, or lower them to harden against guessing:

config vpn ssl settings
    set login-attempt-limit 3        # failed tries before the source IP is blocked (default 2)
    set login-block-time 60          # seconds to keep it blocked
end

Tie this to hygiene: repeated -8s across many users can signal a password-spray — see the FortiBleed response checklist.

05Error -20199: can't reach / establish

Cause. The client never got a usable connection to the SSL-VPN service. Either the server is unreachable (port/firewall/ISP/DNS) or the client stack is in a bad state (corrupted Internet/TLS settings, a proxy, or a wedged FortiClient).

On the client: first prove reachability to the exact SSL-VPN port, then reset the Windows Internet/TLS stack that FortiClient rides on:

# Prove you can reach the SSL-VPN port (default 443, or your custom port)
Test-NetConnection vpn.example.com -Port 443     # PowerShell

# Reset Internet Options (fixes a surprising share of -20199 / -5029), run as Administrator:
RunDll32.exe InetCpl.cpl,ResetIEtoDefaults

Also check for a system proxy, temporarily disable a competing VPN/endpoint agent, and update or reinstall FortiClient if it's stale.

On the FortiGate: confirm the service is actually listening where you think:

get vpn ssl settings | grep -i port          # the port SSL-VPN is listening on
get vpn ssl monitor                          # do any clients connect at all?

06Error -5029: TLS version mismatch

Cause. Client and FortiGate share no common TLS version, so the handshake dies early (the classic "stuck at 31%"). Modern FortiGates require TLS 1.2/1.3; an old client — or a Windows box with TLS 1.2 disabled in Internet Options — has nothing to offer. (A related variant is the client not trusting the server certificate.)

On the client: enable modern TLS: Internet Options → Advanced → tick Use TLS 1.2 (and 1.3 if present), untick SSL 3.0/TLS 1.0, then reset if needed with the command in §05. Update FortiClient to a build that speaks TLS 1.2+.

On the FortiGate: make sure the minimum TLS you require is one the client can actually meet (don't drop below 1.2 in production for anything but a short, deliberate bridge):

config vpn ssl settings
    set ssl-min-proto-version tls1-2         # align with what your clients support
end
Note: lowering ssl-min-proto-version weakens security — prefer upgrading the
client. Also serve a certificate signed by a trusted/public CA on the SSL-VPN
so the client doesn't stall on an untrusted-cert prompt hidden behind a window.

07One server-side trace that covers them all

When the code alone doesn't settle it, watch the whole SSL-VPN conversation from the FortiGate — TLS, auth, and portal in one stream:

diagnose debug reset
diagnose debug application sslvpn -1          # the SSL-VPN daemon (TLS + tunnel setup)
diagnose debug application fnbamd -1          # authentication (user / group / 2FA)
diagnose debug console timestamp enable
diagnose debug enable
# … reproduce the FortiClient connection now …
diagnose debug disable
diagnose debug reset

get vpn ssl monitor                           # who actually made it in

Read it top-down: a failure in the TLS lines is -5029/-20199 territory; a failure in the fnbamd lines is -14; a block message is -8. The stream tells you which section owns the problem.

08References