Error 401 unauthorized

"I accidentally sent a download request to: https://huggingface.co/google/gemma-3n-4B-it-lite-rt-lm/.... I have the required permissions and token to read from Hugging Face via my app, using this plugin:

Kotlin

val IntelligentHeaders = createClientPlugin("IntelligentHeaders") {
    val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0"
    val hfToken = "YOUR_TOKEN_HERE"
}

after this, I am receiving a ‘Download Unauthorized’ error."

1 Like

Hmm… I’m not familiar with Kotlin, but the cause might be related to header issues.


What’s going on (most likely)

1) You’re hitting a gated Gemma repo

The actual LiteRT LM repo currently shown for Gemma 3n is google/gemma-3n-E4B-it-litert-lm and it is explicitly marked Gated model: “You can list files but not access them,” and you must review and agree to Google’s usage license while logged in. (Hugging Face)

If the Hugging Face account that created your token has not accepted those terms (or you accepted with a different account), Hugging Face will keep returning 401 Unauthorized for file downloads. (Hugging Face)

2) Your Kotlin “plugin” doesn’t actually add headers

Your snippet defines userAgent and hfToken, but it does not hook into the request pipeline to append headers. In Ktor, you must use something like onRequest { request, _ -> request.headers.append(...) } (or use defaultRequest, or the Auth plugin). (Ktor Framework)

So your requests may be going out without Authorization: Bearer …, which will always produce 401 on gated content.

3) You may be using a blob URL (viewer) instead of a resolve URL (raw download)

The Gemma repo README includes a blob link for the .litertlm file (that’s the web viewer URL). (Hugging Face)
Programmatic downloads should use the raw file endpoint pattern (.../resolve/...), which Hugging Face also uses as the canonical download form. (Hugging Face)

4) Ktor can wait for a 401 challenge before sending credentials (unless configured)

Ktor’s Bearer auth docs explicitly describe an optional sendWithoutRequest { ... } to send credentials without waiting for a 401 response. (Ktor Framework)
This matters when you want the Authorization header on the first request (common with file downloads and redirects).


The “background” in one paragraph

Hugging Face model downloads are plain HTTP requests. For public models you can fetch files anonymously. For private or gated repos, Hugging Face checks (1) that the request is authenticated with a valid token and (2) that the token’s user has been granted access / accepted terms. Gemma repos are commonly gated, and the Gemma 3n LiteRT LM page explicitly requires accepting Google’s license before file access works. (Hugging Face)


What to do for your case (recommended order)

Step 1 — Ensure you’re using the correct repo + you accepted the gate with the same account as the token

Open the Gemma 3n LiteRT LM repo page while logged in and complete the “review and agree” flow. The page states requests are processed immediately. (Hugging Face)

If your URL is ...gemma-3n-4B-it-lite-rt-lm..., that looks like a naming mismatch. The repo currently shown is ...gemma-3n-E4B-it-litert-lm... (note E4B and litert). (Hugging Face)

Step 2 — Verify the token is valid (quick sanity check)

Hugging Face staff/community commonly use api/whoami-v2 to validate tokens. (Hugging Face Forums)

curl -sS https://huggingface.co/api/whoami-v2 \
  -H "Authorization: Bearer $HF_TOKEN"
  • If this returns 401 → token not being sent / wrong token / token revoked.
  • If this succeeds → token is valid; focus on gating acceptance + URL + Ktor header injection.

Step 3 — Use a raw download URL (resolve, not blob)

The repo lists gemma-3n-E4B-it-int4.litertlm in “Files and versions.” (Hugging Face)
Use:

https://huggingface.co/google/gemma-3n-E4B-it-litert-lm/resolve/main/gemma-3n-E4B-it-int4.litertlm

(If you copied a link from the README, it’s a blob viewer link. (Hugging Face))

Step 4 — Fix your Ktor client so the Authorization header is actually attached

Option A (simplest): defaultRequest { bearerAuth(...) }

Ktor provides bearerAuth(token) which appends the Authorization: Bearer ... header. (Ktor API)

import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.defaultRequest
import io.ktor.client.request.*
import io.ktor.http.*

val client = HttpClient(CIO) {
  defaultRequest {
    header(HttpHeaders.UserAgent, "MyApp/1.0")
    bearerAuth(hfToken) // adds Authorization: Bearer <token>
  }
}

This avoids the “plugin that doesn’t hook anything” problem.

Option B (more robust): use Ktor Auth { bearer { … } } and send token preemptively

Ktor’s bearer auth docs show how to configure tokens and sendWithoutRequest. (Ktor Framework)

import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.auth.*
import io.ktor.client.plugins.auth.providers.*
import io.ktor.http.*

val client = HttpClient(CIO) {
  install(Auth) {
    bearer {
      loadTokens { BearerTokens(hfToken, "") }
      sendWithoutRequest { req -> req.url.host == "huggingface.co" }
    }
  }
}

Step 5 — Confirm token permissions/scope

If you’re using a fine-grained token, ensure it includes read access to the specific repo/org. Hugging Face documents fine-grained tokens as resource-scoped. (Hugging Face)


If it still fails after all of the above

  1. Try downloading a public file from Hugging Face with the same client.
    If even public downloads 401, you likely have a token/header injection issue.

  2. If whoami-v2 succeeds but all downloads fail with “Invalid credentials…” or similar, there have been user reports of account/token backend issues (rare, but real). (Hugging Face Forums)


Why the “accidental request” didn’t really “cause” it

A single bad download request doesn’t typically change server-side authorization state. What it does do is reveal that the target repo is gated and/or your client isn’t attaching auth correctly—both of which deterministically produce 401. The Gemma repo itself states it is gated and requires accepting conditions. (Hugging Face)