laurent22/joplin · error · Error

Could not get geolocation from any of the services

Error message

Could not get geolocation from any of the services

What it means

Thrown by GeolocationNode.currentPosition after it iterates every registered GeoIP service (geoipServices map in packages/lib/geolocation-node.ts:27) and each one rejects. Today only the 'ipwhois' service is registered (a GET to https://ipwho.is/), so in practice this fires whenever that single call fails: the HTTP request errors, the response is not ok, or the JSON lacks the required latitude/longitude keys. The per-service failure is swallowed with a logger.warn, so this aggregate error is the only signal the caller receives.

Source

Thrown at packages/lib/geolocation-node.ts:59

	},

};

export default class {
	public static async currentPosition(options: CurrentPositionOptions = null) {
		if (!options) options = {};

		for (const [serviceName, handler] of Object.entries(geoipServices)) {
			try {
				const response = await handler();
				return response;
			} catch (error) {
				logger.warn(`Could not get geolocation from service "${serviceName}"`);
				logger.warn(error);
			}
		}

		throw new Error('Could not get geolocation from any of the services');
	}
}

View on GitHub (pinned to 2654b33620)

Solutions

  1. Confirm outbound connectivity to https://ipwho.is/ from the host (curl -sS https://ipwho.is/ | jq) and check the logged upstream warning printed just before this throw — it carries the real cause.
  2. If the host is permanently offline or behind a proxy, register an additional GeoipService in geoipServices or supply a local fallback rather than relying on the single ipwho.is entry.
  3. Verify shim.fetch is initialized (packages/lib/shim-init-node.ts) before currentPosition is called; an unset fetch will reject on every service.
  4. Make callers tolerate geolocation failure — catch the error and degrade to a default coordinate instead of treating it as fatal.

Example fix

// before
const pos = await GeolocationNode.currentPosition();

// after
let pos;
try {
  pos = await GeolocationNode.currentPosition();
} catch (error) {
  logger.warn('Geolocation unavailable, falling back to default', error);
  pos = { timestamp: Date.now(), coords: { latitude: 0, longitude: 0, altitude: 0 } };
}
Defensive patterns

Strategy: fallback

Validate before calling

// Cheap pre-flight: only attempt geolocation if the host can reach the upstream.
// Reuse the same transport the service uses.
async function canReachIpwhois(): Promise<boolean> {
  try {
    const r = await shim.fetch('https://ipwho.is/', { method: 'HEAD' });
    return r.ok;
  } catch {
    return false;
  }
}

if (!(await canReachIpwhois())) {
  return defaultPosition();
}
return await GeolocationNode.currentPosition();

Try / catch

// Geolocation is best-effort; never let it abort the surrounding flow.
let position: CurrentPositionResponse;
try {
  position = await GeolocationNode.currentPosition();
} catch (error) {
  logger.warn('Geolocation lookup failed, using default coordinates', error);
  position = {
    timestamp: Date.now(),
    coords: { latitude: 0, longitude: 0, altitude: 0 },
  };
}

Prevention

When it happens

Trigger: Calling GeolocationNode.currentPosition() when: (1) the host has no outbound network, (2) https://ipwho.is/ returns a non-2xx status (response.ok is false -> 'Could not get geolocation: ...'), (3) the endpoint returns a body without 'latitude'/'longitude' (e.g. an error object like { success:false, error:{...} }), or (4) shim.fetch itself throws (proxy/DNS/TLS). Because ipwhois is the only entry, any single failure escalates straight to this throw.

Common situations: Offline or air-gapped CI runners; corporate proxies that block ipwho.is; ipwho.is being down or rate-limiting; the upstream API contract changing shape; a Node shim where shim.fetch was never wired (shim-init-node). Often surfaces as a startup/location-defaulting failure on desktop/CLI builds.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/7e14268808cd13b0. Report an issue: GitHub.