YoKeyword/Fragmentation · error · IllegalStateException

Can't find container, please call loadRootFragment() first!

Error message

Can't find container, please call loadRootFragment() first!

What it means

getTopFragmentForStart determines which container a new fragment goes into based on the 'from' fragment's containerId. If the from fragment has mContainerId == 0 and was never added via a viewpager adapter (tag not starting with 'android:switcher:'), the library cannot locate a container and throws an IllegalStateException.

Solutions

  1. Load the fragment with loadRootFragment()/start() so the containerId is bound before navigating from it.
  2. If the fragment is inside a viewpager, add it via the library's FragmentPagerAdapter so the 'android:switcher:' tag is set.
  3. Ensure the from fragment was added to a container with a valid container id (bind via SupportFragmentDelegate.mContainerId).

Example fix

// before
getFragmentManager().beginTransaction().add(R.id.fl, myFragment, "mine").commit();
myFragment.start(new DetailFragment());
// after
loadRootFragment(R.id.fl, myFragment);
// later
myFragment.start(new DetailFragment());
Defensive patterns

Strategy: validation

Validate before calling

if (fromFragment.getSupportDelegate().mContainerId == 0 && (fromFragment.getTag() == null || !fromFragment.getTag().startsWith("android:switcher:"))) {
    // load via library APIs before starting navigation
}

Prevention

When it happens

Trigger: Calling start()/startForResult() from a fragment that was never added through loadRootFragment or a viewpager, so its containerId is still 0 and its tag is a custom/unknown tag.

Common situations: Manually adding a SupportFragment with a plain FragmentTransaction then starting navigation from it; fragments created programmatically and added with custom tags; nested fragments not loaded via the library APIs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of YoKeyword/Fragmentation@0394930a3e (2026-09-10). Data as JSON: /api/errors/293c3c59719aeba2. Report an issue: GitHub.

Appendix: source

Thrown at fragmentation_core/src/main/java/me/yokeyword/fragmentation/TransactionDelegate.java:388

            if (transactionRecord.sharedElementList != null) {
                sharedElementList = transactionRecord.sharedElementList;
            }
        }

        if (handleLaunchMode(fm, from, to, toFragmentTag, launchMode)) return;

        start(fm, from, to, toFragmentTag, dontAddToBackStack, sharedElementList, false, type);
    }

    private ISupportFragment getTopFragmentForStart(ISupportFragment from, FragmentManager fm) {
        ISupportFragment top;
        if (from == null) {
            top = SupportHelper.getTopFragment(fm);
        } else {
            if (from.getSupportDelegate().mContainerId == 0) {
                Fragment fromF = (Fragment) from;
                if (fromF.getTag() != null && !fromF.getTag().startsWith("android:switcher:")) {
                    throw new IllegalStateException("Can't find container, please call loadRootFragment() first!");
                }
            }
            top = SupportHelper.getTopFragment(fm, from.getSupportDelegate().mContainerId);
        }
        return top;
    }

    private void start(FragmentManager fm, final ISupportFragment from, ISupportFragment to, String toFragmentTag,
                       boolean dontAddToBackStack, ArrayList<TransactionRecord.SharedElement> sharedElementList, boolean allowRootFragmentAnim, int type) {
        FragmentTransaction ft = fm.beginTransaction();
        boolean addMode = (type == TYPE_ADD || type == TYPE_ADD_RESULT || type == TYPE_ADD_WITHOUT_HIDE || type == TYPE_ADD_RESULT_WITHOUT_HIDE);
        Fragment fromF = (Fragment) from;
        Fragment toF = (Fragment) to;
        Bundle args = getArguments(toF);
        args.putBoolean(FRAGMENTATION_ARG_REPLACE, !addMode);

        if (sharedElementList == null) {
            if (addMode) { // Replace mode forbidden animation, the replace animations exist overlapping Bug on support-v4.

View on GitHub (pinned to 0394930a3e)