stride3d/stride · error · InvalidOperationException

Can't pack files.

Error message

Can't pack files.

What it means

ObjectDatabase.CreateBundle throws this when the bundle backend (IOdbBackend for writing bundles) is null. Bundles are prepacked asset files; without a valid BundleOdbBackend there is nowhere to write the pack, so the library refuses rather than fail later. Callers typically get here via topBundleUrl when preparing asset bundles.

Solutions

  1. Configure the ObjectDatabase with a valid BundleOdbBackend (BundleDirectory set) before calling CreateBundle.
  2. Run bundle creation from the game studio/asset compiler where a writable bundle backend is attached, not at runtime from a read-only database.
  3. Guard the call site: skip or log when bundleBackend is null instead of invoking CreateBundle.

Example fix

// before
var url = database.CreateBundle(objectIds, bundleName, null, disableCompressionIds, indexMap, dependencies, false);
// after
var backend = new BundleOdbBackend(database, bundleDirectory, VirtualFileSystem.GetFileProvider(bundleDirectory));
if (backend == null) throw new InvalidOperationException("Bundle backend not configured");
var url = database.CreateBundle(objectIds, bundleName, backend, disableCompressionIds, indexMap, dependencies, false);
Defensive patterns

Strategy: validation

Validate before calling

if (bundleBackend == null)
    throw new InvalidOperationException("CreateBundle requires a configured BundleOdbBackend; initialize the object database with a writable bundle backend first.");

Try / catch

try { url = database.CreateBundle(ids, name, backend, ...); }
catch (InvalidOperationException ex) when (ex.Message == "Can't pack files.") {
    logger.Error("Bundle backend not configured; cannot pack assets.");
}

Prevention

When it happens

Trigger: Calling ObjectDatabase.CreateBundle (directly or via topBundleUrl) when the object database was opened without a bundle-capable write backend (bundleBackend parameter null).

Common situations: Opening a read-only object database (e.g. mounted from an APK or read-only asset store) and then attempting to generate bundles; forgetting to configure BundleOdbBackend in the game asset compiler/packager; passing a null backend programmatically.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/a8154c4f104496f8. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Serialization/Storage/ObjectDatabase.cs:144

    }

    public void Dispose()
    {
        backendRead1.Dispose();
        if (backendRead2 != null && !ReferenceEquals(backendRead2, backendRead1))
        {
            backendRead2.Dispose();
        }
        if (backendWrite != null && !ReferenceEquals(backendRead2, backendWrite) && !ReferenceEquals(backendRead2, backendRead1))
        {
            backendWrite.Dispose();
        }
    }

    public string? CreateBundle(ObjectId[] objectIds, string bundleName, BundleOdbBackend bundleBackend, ISet<ObjectId> disableCompressionIds, Dictionary<string, ObjectId> indexMap, IList<string> dependencies, bool useIncrementalBundle)
    {
        if (bundleBackend == null)
            throw new InvalidOperationException("Can't pack files.");

        if (objectIds.Length == 0)
            return null;

        var packUrl = bundleBackend.BundleDirectory + bundleName + BundleOdbBackend.BundleExtension; // we don't want the pack to be compressed in the APK on android

        // Create pack
        BundleOdbBackend.CreateBundle(packUrl, backendRead1, objectIds, disableCompressionIds, indexMap, dependencies, useIncrementalBundle);
        return packUrl;
    }

    public bool TryGetObjectLocation(ObjectId objectId, [NotNullWhen(true)] out string? filePath, out long start, out long end)
    {
        if (BundleBackend != null && BundleBackend.TryGetObjectLocation(objectId, out filePath, out start, out end))
            return true;

        foreach (var backend in new[] { backendRead1, backendRead2 })
        {

View on GitHub (pinned to 96fad776d2)