apache/cordova-android · critical · RuntimeException

Failed to create webview.

Error message

Failed to create webview. 

What it means

Cordova instantiates its WebView engine reflectively. CordovaWebViewImpl.createEngine reads the <preference name="webview"> value from config.xml (default: org.apache.cordova.engine.SystemWebViewEngine), loads that class with Class.forName, and calls its (Context, CordovaPreferences) constructor. Any failure in that chain — ClassNotFoundException (bad class name / plugin not on classpath), NoSuchMethodException (missing 2-arg constructor), ClassCastException, or an exception thrown inside the engine's own constructor — is rethrown wrapped in this RuntimeException.

Source

Thrown at framework/src/org/apache/cordova/CordovaWebViewImpl.java:84

    private boolean hasPausedEver;

    // The URL passed to loadUrl(), not necessarily the URL of the current page.
    String loadedUrl;

    /** custom view created by the browser (a video player for example) */
    private View mCustomView;
    private WebChromeClient.CustomViewCallback mCustomViewCallback;

    private Set<Integer> boundKeyCodes = new HashSet<Integer>();

    public static CordovaWebViewEngine createEngine(Context context, CordovaPreferences preferences) {
        String className = preferences.getString("webview", SystemWebViewEngine.class.getCanonicalName());
        try {
            Class<?> webViewClass = Class.forName(className);
            Constructor<?> constructor = webViewClass.getConstructor(Context.class, CordovaPreferences.class);
            return (CordovaWebViewEngine) constructor.newInstance(context, preferences);
        } catch (Exception e) {
            throw new RuntimeException("Failed to create webview. ", e);
        }
    }

    public CordovaWebViewImpl(CordovaWebViewEngine cordovaWebViewEngine) {
        this.engine = cordovaWebViewEngine;
    }

    // Convenience method for when creating programmatically (not from Config.xml).
    public void init(CordovaInterface cordova) {
        init(cordova, new ArrayList<PluginEntry>(), new CordovaPreferences());
    }

    @SuppressLint("Assert")
    @Override
    public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences) {
        if (this.cordova != null) {
            throw new IllegalStateException();
        }

View on GitHub (pinned to 7c1e190064)

Solutions

  1. Read the wrapped cause in the stack trace: ClassNotFoundException means the class name/plugin is wrong; InvocationTargetException means the engine's constructor threw — fix whatever its cause says.
  2. If you do not need a custom engine, delete the <preference name="webview" .../> line from config.xml so the default SystemWebViewEngine is used, then cordova prepare android.
  3. If you do need it, reinstall the engine plugin (cordova plugin ls / cordova plugin add <engine-plugin>) and verify the preference value exactly matches the engine class's fully-qualified name.
  4. For a custom engine, make the class public, implement CordovaWebViewEngine, and expose a public (Context, CordovaPreferences) constructor.
  5. For minified release builds, add a ProGuard/R8 keep rule for the engine class and its constructor.

Example fix

// before — config.xml references an engine whose plugin was removed
<preference name="webview" value="com.example.FastWebViewEngine" />

// after — option A: drop the preference and use the built-in engine
<!-- default SystemWebViewEngine is used -->

// after — option B: restore the class via its plugin
// cordova plugin add cordova-plugin-fast-webview
<preference name="webview" value="com.example.FastWebViewEngine" />
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the configured engine class loads before creating the engine
String engineClass = preferences.getString("webview", SystemWebViewEngine.class.getCanonicalName());
try {
    Class<?> cls = Class.forName(engineClass); // fails fast with a clear ClassNotFoundException
    cls.getConstructor(Context.class, CordovaPreferences.class); // constructor present?
} catch (ReflectiveOperationException e) {
    throw new IllegalStateException("Webview engine class " + engineClass + " is not usable; check the <preference name=\"webview\"/> and the engine plugin install", e);
}

Try / catch

try {
    engine = CordovaWebViewImpl.createEngine(context, preferences);
} catch (RuntimeException e) {
    Throwable cause = e.getCause() != null ? e.getCause() : e;
    if (cause instanceof ClassNotFoundException) {
        // bad <preference name="webview"> value or engine plugin missing — fix config.xml / reinstall plugin
    } else if (cause instanceof NoSuchMethodException) {
        // engine lacks the required (Context, CordovaPreferences) constructor
    } else {
        // engine constructor threw; inspect cause for the real failure
    }
    throw new IllegalStateException("Webview engine failed to initialize", cause);
}

Prevention

When it happens

Trigger: config.xml contains <preference name="webview" value="com.example.MyEngine"/> but the engine plugin providing that class was removed or never installed; the FQN has a typo; a custom engine class lacks a public constructor taking (Context, CordovaPreferences); the engine's constructor itself throws (missing dependency, unsupported Android version); R8/ProGuard strips or renames the engine class in a release build.

Common situations: A custom webview engine plugin (e.g. a Crosswalk-style or vendor WebView engine) is uninstalled while its config.xml preference remains; projects migrated between cordova-android majors carry stale preferences; engine plugin installed but incompatible with the current platform release; release builds obfuscating the reflectively-loaded class.

Related errors


AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22). Data as JSON: /api/errors/09d8efac63683b88. Report an issue: GitHub.