gethomepage/homepage · error · Error

TrueNAS authentication failed

Error message

TrueNAS authentication failed

What it means

Thrown at the end of authenticate() when neither the API-key path nor the username/password path returned true. The function tries auth.login_with_api_key first (if widget.key is set) and falls back to auth.login with username+password; only if both are absent or both fail does it raise. This is therefore a terminal 'no usable credential' error.

Source

Thrown at src/widgets/truenas/proxy.js:101

async function authenticate(ws, widget) {
  if (widget?.key) {
    try {
      const apiKeyResult = await sendMethod(ws, "auth.login_with_api_key", [widget.key]);
      if (apiKeyResult === true) return;
      logger.warn("TrueNAS API key authentication failed, falling back to username/password when available.");
    } catch (err) {
      logger.error("TrueNAS API key authentication failed: %s", err?.message ?? err);
    }
  }

  if (widget?.username && widget?.password) {
    const loginResult = await sendMethod(ws, "auth.login", [widget.username, widget.password]);
    if (loginResult === true) return;
    logger.warn("TrueNAS username/password authentication failed.");
  }

  throw new Error("TrueNAS authentication failed");
}

export default async function truenasProxyHandler(req, res, map) {
  const { group, service, endpoint, index } = req.query;
  if (!group || !service) {
    logger.debug("Invalid or missing service '%s' or group '%s'", service, group);
    return res.status(400).json({ error: "Invalid proxy service type" });
  }

  const widget = await getServiceWidget(group, service, index);

  if (!widget) {
    logger.debug("Invalid or missing widget for service '%s' in group '%s'", service, group);
    return res.status(400).json({ error: "Invalid proxy service type" });
  }

  if (!endpoint) {
    return res.status(204).end();

View on GitHub (pinned to b6dca1ae03)

Solutions

  1. In TrueNAS, create/verify an API key (System > API Keys) and paste it into the widget's key field; prefer the API-key path.
  2. If using username/password, confirm the account is enabled and the password is current.
  3. Check the Homepage debug log for the two preceding warnings/errors ('API key authentication failed', 'username/password authentication failed') to see which path failed.
  4. Ensure the TrueNAS websocket URL is correct and that the Homepage host's IP is not blocked by TrueNAS access rules.
  5. If both methods are configured but both fail, test the API key directly with curl against the TrueNAS websocket/JSON-RPC endpoint.
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify at least one TrueNAS credential path is configured and non-empty.
function hasTruenasCredentials(w) {
  return Boolean(
    (typeof w?.key === "string" && w.key.length > 0) ||
    (typeof w?.username === "string" && typeof w?.password === "string" && w.username && w.password),
  );
}
if (!hasTruenasCredentials(widget)) throw new Error("TrueNAS widget has no API key and no username/password");

Type guard

function isTruenasWidgetAuthenticatable(w) {
  return Boolean(w) && (Boolean(w.key) || (Boolean(w.username) && Boolean(w.password)));
}

Try / catch

try {
  await authenticate(ws, widget);
} catch (err) {
  if (/authentication failed/i.test(err.message)) {
    res.status(401).json({ error: "TrueNAS authentication failed", hint: "verify API key or username/password" });
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: widget.key is missing/invalid AND username/password are missing or wrong; API key auth throws (logged at error level) and no credentials are configured for the fallback; TrueNAS middleware websocket rejects both methods (wrong app version, locked account, IP not allowed).

Common situations: Only an API key configured but the key was revoked in TrueNAS; only username/password configured but the password changed; TrueNAS SCALE vs CORE version mismatch changing the auth.login behavior; TrueNAS IP-denylist blocking the Homepage host; credential fields left empty in the widget config.

Understand the failure class

Related errors


AI-assisted analysis of gethomepage/homepage@b6dca1ae03 (2026-08-13). Data as JSON: /api/errors/365d15dcc4a705a2. Report an issue: GitHub.