{"record":{"id":"72355512c69170db","repo":"stride3d/stride","slug":"assetitem-must-be-an-absolute-path","errorCode":null,"errorMessage":"assetItem must be an absolute path","messagePattern":"assetItem must be an absolute path","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/assets/Stride.Core.Assets/Compiler/AssetCompilerBase.cs","lineNumber":55,"sourceCode":"    {\n        yield break;\n    }\n\n    public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem assetItem)\n    {\n        ArgumentNullException.ThrowIfNull(context);\n        ArgumentNullException.ThrowIfNull(assetItem);\n\n        var result = new AssetCompilerResult(GetType().Name)\n        {\n            BuildSteps = new AssetBuildStep(assetItem)\n        };\n\n        // Only use the path to the asset without its extension\n        var fullPath = assetItem.FullPath;\n        if (!fullPath.IsAbsolute)\n        {\n            throw new InvalidOperationException(\"assetItem must be an absolute path\");\n        }\n\n        // Try to compile only if we're sure that the sources exist.\n        if (EnsureSourcesExist(result, assetItem))\n        {\n            Prepare(context, assetItem, assetItem.Location.GetDirectoryAndFileName(), result);\n        }\n\n        return result;\n    }\n\n    /// <summary>\n    /// Compiles the asset from the specified package.\n    /// </summary>\n    /// <param name=\"context\">The context to use to compile the asset.</param>\n    /// <param name=\"assetItem\">The asset to compile</param>\n    /// <param name=\"targetUrlInStorage\">The absolute URL to the asset, relative to the storage.</param>\n    /// <param name=\"result\">The result where the commands and logs should be output.</param>","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/assets/Stride.Core.Assets/Compiler/AssetCompilerBase.cs#L37-L73","documentation":"AssetCompilerBase.Prepare derives the compilation output path from the asset item's FullPath, which must be absolute to be deterministic and resolvable on disk. If the passed AssetItem's FullPath is relative, it throws InvalidOperationException because relative paths cannot be used to locate/create compiler outputs.","triggerScenarios":"Calling Prepare (directly or through AssetCompilerRegistry/asset compilation pipeline) with an AssetItem constructed from a relative UFile path, e.g. new AssetItem(\"myasset\", descriptor) where the source path was never rooted against a package/project directory.","commonSituations":"Building assets outside the normal package pipeline where paths were not resolved via package root; custom tooling constructing AssetItem from command-line relative paths; tests creating AssetItems without an absolute source path.","solutions":["Resolve the asset path against the package/project root to an absolute UFile before creating the AssetItem.","Check fullPath.IsAbsolute yourself and convert with UPath.Combine(baseDir, relativePath) before calling Prepare.","If you only have a relative path, obtain the containing Package's root directory and combine it with the asset location.","Fix the upstream code that produced the relative path (e.g. missing Package root in a session/package container)."],"exampleFix":"// before\nvar item = new AssetItem(new UFile(\"assets/my/logo.sdtasy\"), descriptor);\ncompiler.Prepare(context, item);\n// after\nvar abs = UPath.Combine(\"/path/to/project\", \"assets/my/logo.sdtasy\");\nvar item = new AssetItem(new UFile(abs), descriptor);\ncompiler.Prepare(context, item);","handlingStrategy":"validation","validationCode":"if (!assetItem.FullPath.IsAbsolute)\n    assetItem.FullPath = UPath.Combine(packageRootDirectory, assetItem.FullPath);","typeGuard":"static bool HasAbsolutePath(AssetItem item) => item?.FullPath != null && item.FullPath.IsAbsolute;","tryCatchPattern":"try\n{\n    compiler.Prepare(context, assetItem);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"absolute path\"))\n{\n    logger.Error($\"Asset {assetItem?.Location} has a relative path; resolve it against the package root first.\");\n}","preventionTips":["Always construct AssetItem from paths resolved through the package/container root.","Never pass command-line relative paths straight into asset compilation.","Add an assertion in your tooling that all asset paths are absolute before compiling."],"tags":["path","asset-compilation","precondition","invalid-state"],"backgroundTag":"invalid-url-format","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}