> ## Documentation Index
> Fetch the complete documentation index at: https://developers.learn.ink/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Fixes for the problems beta testers hit most often

<Note>
  **Beta.** If none of these solve it, email [support@learn.ink](mailto:support@learn.ink)
  with your framework, the SDK tag you checked out, and the error. We reply quickly to beta
  participants.
</Note>

## A login screen appears instead of the content

This is the most common first-run problem, and it almost always means **the sign-in token
never reached LearnInk**. The SDK deliberately falls back to loading LearnInk signed-out
rather than showing an error, so a broken token flow looks like a login screen.

Work through it in this order:

<Steps>
  <Step title="Check your backend endpoint directly">
    Call it with curl, exactly as your app does:

    ```bash theme={null}
    curl -i -X POST https://your-api.example.com/auth/learnink \
      -H "Content-Type: application/json" \
      -d '{"id":"test-user-1"}'
    ```

    You need **HTTP 200** and a body containing a `token` field. Anything else — 404, 401,
    500, a token that is `null` — is a backend problem, not an SDK problem. See
    [Step 1 of the WebView setup guide](/integration/webview-setup-guide).
  </Step>

  <Step title="Check the org ID matches the API key">
    Your API key belongs to one organisation. If the `orgId` you passed to the SDK is not
    the organisation that key belongs to, the Identify API rejects it. Both must be the
    same organisation.
  </Step>

  <Step title="Log the failure">
    Implement `onAuthenticationFailed` — it receives the exact error from your
    `fetchToken` function, which usually names the problem immediately.

    <CodeGroup>
      ```kotlin Kotlin theme={null}
      override fun onAuthenticationFailed(error: Throwable) {
          Log.e("LearnInk", "Token fetch failed", error)
      }
      ```

      ```dart Flutter theme={null}
      onAuthenticationFailed: (message) => debugPrint('LearnInk: $message'),
      ```

      ```tsx React Native theme={null}
      onAuthenticationFailed={(message) => console.warn('LearnInk:', message)}
      ```
    </CodeGroup>
  </Step>

  <Step title="Check the device can reach your backend">
    An emulator cannot reach `localhost` on your machine — that is the emulator itself.
    Use `10.0.2.2` for the Android emulator host, a LAN IP for a physical device, or a
    tunnelling tool. If your backend is behind a VPN, the device needs it too.
  </Step>
</Steps>

## Gradle cannot find `ink.learn:learnink-sdk`

```
Could not find ink.learn:learnink-sdk:0.1.0
```

Two possible causes:

**You have not built the SDK.** Run it now:

```bash theme={null}
cd learnink-sdk/android && ./gradlew :sdk:publishToMavenLocal
```

**`mavenLocal()` is in the wrong place.** It must be where your app resolves
*dependencies*, not where it resolves *plugins*. In a modern project that is
`dependencyResolutionManagement { repositories { … } }` in `settings.gradle.kts`, **not**
`pluginManagement`. Confirm the SDK actually published:

```bash theme={null}
ls ~/.m2/repository/ink/learn/learnink-sdk/
```

You should see a `0.1.0` directory.

## "Gradle requires JVM 17 or later"

Your default JDK is too old. For a one-off command:

```bash theme={null}
JAVA_HOME=$(/usr/libexec/java_home -v 21) ./gradlew :sdk:publishToMavenLocal
```

For Flutter, set it permanently — Flutter often defaults to an older bundled JDK:

```bash theme={null}
flutter config --jdk-dir "$(/usr/libexec/java_home -v 21)"
```

For Android Studio: **Settings → Build, Execution, Deployment → Build Tools → Gradle →
Gradle JDK**.

## Nothing renders — blank space where LearnInk should be

Almost always a layout problem: the view has **zero height**.

| Framework      | Fix                                                                                |
| -------------- | ---------------------------------------------------------------------------------- |
| Native Android | In a `LinearLayout`, use `height = 0` with `layout_weight = 1`, not `wrap_content` |
| Flutter        | Wrap in `Expanded` inside a `Column` or `Row`                                      |
| React Native   | Give it `flex: 1` or explicit dimensions                                           |

## React Native: LearnInk appears but does not respond to taps

You have rendered it inside a React Native `Modal`. On the new architecture, touches do
not reach native views hosted in a `Modal`.

Use a dedicated screen in your navigator, or a conditionally rendered full-screen `View`:

```tsx theme={null}
{visible && (
  <SafeAreaView style={StyleSheet.absoluteFill}>
    <LearnInkWebView /* … */ style={{ flex: 1 }} />
  </SafeAreaView>
)}
```

## React Native: red screen mentioning `PlatformConstants`

```
[runtime not ready]: Invariant Violation: TurboModuleRegistry.getEnforcing(...):
'PlatformConstants' could not be found
```

Your app loaded its JavaScript from **a different dev server** — usually another React
Native or Expo project already running on port 8081. Emulators reach the dev server
directly, bypassing `adb reverse`, so they get the other project's bundle.

Stop the other dev server, or start yours on a free port and rebuild so the app knows
about it:

```bash theme={null}
npx react-native start --port 8082
```

```bash theme={null}
cd android && ./gradlew installDebug -PreactNativeDevServerPort=8082
```

## React Native: Metro cannot resolve the package

If you installed with a filesystem path rather than the tarball, npm created a symlink and
Metro will not follow it without extra configuration. Reinstall from the tarball instead:

```bash theme={null}
npm install /path/to/learnink-react-native-sdk-0.1.0.tgz
```

See [Step 2 of the React Native guide](/sdk/react-native).

## `AbstractMethodError` mentioning `LearnInkEventListener`

You are running a stale build — some classes were compiled against an older version of the
SDK. Clean and rebuild:

```bash theme={null}
cd android && ./gradlew clean
```

Then rebuild your app. If it persists, confirm every machine has rebuilt the SDK at the
same tag.

## The content is stale, or a user seems signed in as someone else

The SDK caches LearnInk content and session state on the device, as any browser would.
When your app's user signs out, clear the LearnInk state too:

```kotlin theme={null}
LearnInk.reset()
```

<Warning>
  If your app supports **multiple users on one device**, call this on every sign-out.
  Otherwise the next user may briefly see cached content belonging to the previous one.
</Warning>

## Content does not appear offline

Work through [Offline behaviour](/sdk/offline) first — in particular, the user must have
opened LearnInk online at least once on that device.

If cached content still does not appear on a device you know has been online, the web
app's offline capability may not be enabled for your organisation yet. Contact
[support@learn.ink](mailto:support@learn.ink).

## Inspecting what is actually happening

The SDK enables WebView debugging automatically for **debug builds** of your app. With the
device connected:

<Steps>
  <Step title="Open chrome://inspect in desktop Chrome">
    Your app's WebView appears in the list.
  </Step>

  <Step title="Click inspect">
    You get full DevTools for the LearnInk page.
  </Step>

  <Step title="Check the Network tab">
    Confirm the page URL carries a `token` parameter. If it does not, the token never
    reached the SDK — go back to the login screen section above.
  </Step>

  <Step title="Check the Application tab">
    Under **Cache Storage** you can see exactly what has been downloaded for offline use.
  </Step>
</Steps>

This is the fastest way to tell an SDK problem from a backend or content problem, and it
is what we will ask you for if you contact support.

## Reporting a problem

Email [support@learn.ink](mailto:support@learn.ink) with:

* Your framework and version (`flutter --version`, `npx react-native --version`, or AGP/Kotlin versions)
* The SDK tag you checked out (e.g. `v0.1.0`)
* What you expected and what happened
* Any output from `onAuthenticationFailed` or `onWebResourceError`
* A logcat extract if the app crashed
