{"record":{"id":"8404299a9360ae1f","repo":"immich-app/immich","slug":"server-is-not-reachable","errorCode":null,"errorMessage":"Server is not reachable","messagePattern":"Server is not reachable","errorType":"http","errorClass":"ApiException","httpStatus":503,"severity":"error","filePath":"mobile/lib/services/api.service.dart","lineNumber":104,"sourceCode":"\n  /// Takes a server URL and attempts to resolve the API endpoint.\n  ///\n  /// Input: [schema://]host[:port][/path]\n  ///  schema - optional (default: https)\n  ///  host   - required\n  ///  port   - optional (default: based on schema)\n  ///  path   - optional\n  Future<String> resolveEndpoint(String serverUrl) async {\n    String url = normalizeServerUrl(serverUrl);\n\n    // Check for /.well-known/immich\n    final wellKnownEndpoint = await _getWellKnownEndpoint(url);\n    if (wellKnownEndpoint.isNotEmpty) {\n      url = normalizeServerUrl(wellKnownEndpoint);\n    }\n\n    if (!await _isEndpointAvailable(url)) {\n      throw ApiException(503, \"Server is not reachable\");\n    }\n\n    // Otherwise, assume the URL provided is the api endpoint\n    return url;\n  }\n\n  Future<bool> _isEndpointAvailable(String serverUrl) async {\n    final endpoint = serverUrl.endsWith('/api') ? serverUrl : '$serverUrl/api';\n\n    try {\n      setEndpoint(endpoint);\n      await serverInfoApi.pingServer().timeout(const Duration(seconds: 5));\n    } on TimeoutException catch (_) {\n      return false;\n    } on SocketException catch (_) {\n      return false;\n    } catch (error, stackTrace) {\n      _log.severe(\"Error while checking server availability\", error, stackTrace);","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/mobile/lib/services/api.service.dart#L86-L122","documentation":"The API service resolves the server URL and probes it with _isEndpointAvailable; if the endpoint does not respond, it throws an ApiException with HTTP status 503 meaning the server cannot be reached. It is used during server-URL validation/normalization (e.g. login flow).","triggerScenarios":"Calling the server URL resolution routine where _getWellKnownEndpoint succeeds (or is empty) but _isEndpointAvailable(url) returns false — connection refused, DNS failure, TLS error, or non-reachable host on the resolved URL.","commonSituations":"User typos the server URL in the login screen; self-hosted Immich server is stopped or behind a misconfigured reverse proxy; firewall/VPN blocks the port; well-known endpoint redirects to an unreachable address.","solutions":["Verify the server URL is reachable (curl -v <url>) from the client's network","Start the Immich server / check container health and port mappings","Check reverse proxy, TLS certificate, and firewall rules for the host","Show a retry/network-status message in the UI instead of proceeding"],"exampleFix":"// before\nfinal url = 'https://immich.example.com:2283/app'; // typo path\n// after\nfinal url = 'https://immich.example.com:2283'; // correct base URL, verified reachable","handlingStrategy":"retry","validationCode":"final uri = Uri.tryParse(rawUrl);\nif (uri == null || !uri.hasScheme || !uri.host.isNotEmpty) throw FormatException('bad url');\nfinal ok = await http.head(uri.replace(path: '/api/server/ping')).timeout(5s);","typeGuard":"bool isValidServerUrl(String url) => Uri.tryParse(url) != null && Uri.parse(url).hasScheme;","tryCatchPattern":"try {\n  final endpoint = await api.resolveServerUrl(url);\n} on ApiException catch (e) {\n  if (e.status == 503) promptRetryWithNetworkStatus();\n  else rethrow;\n}","preventionTips":["Validate URL format before calling resolution","Ping the server with a short timeout before login","Show connectivity status and offer retry in the UI","Document correct server URL format (no /api suffix) to users"],"tags":["network","http","connectivity","api"],"backgroundTag":"connection-refused","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}