stride3d/stride · error · InvalidOperationException
assetItem must be an absolute path
Error message
assetItem must be an absolute path
What it means
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.
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).
Example fix
// before
var item = new AssetItem(new UFile("assets/my/logo.sdtasy"), descriptor);
compiler.Prepare(context, item);
// after
var abs = UPath.Combine("/path/to/project", "assets/my/logo.sdtasy");
var item = new AssetItem(new UFile(abs), descriptor);
compiler.Prepare(context, item); Defensive patterns
Strategy: validation
Validate before calling
if (!assetItem.FullPath.IsAbsolute)
assetItem.FullPath = UPath.Combine(packageRootDirectory, assetItem.FullPath); Type guard
static bool HasAbsolutePath(AssetItem item) => item?.FullPath != null && item.FullPath.IsAbsolute;
Try / catch
try
{
compiler.Prepare(context, assetItem);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("absolute path"))
{
logger.Error($"Asset {assetItem?.Location} has a relative path; resolve it against the package root first.");
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- The relativePath argument is null or empty
- Could not find asset
- Expect name1=value1;name2=value2 format.
- Type [ ] must be assignable to Asset
- The BuildSteps property cannot be set to null
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/72355512c69170db.
Report an issue: GitHub.
Appendix: source
Thrown at sources/assets/Stride.Core.Assets/Compiler/AssetCompilerBase.cs:55
{
yield break;
}
public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem assetItem)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(assetItem);
var result = new AssetCompilerResult(GetType().Name)
{
BuildSteps = new AssetBuildStep(assetItem)
};
// Only use the path to the asset without its extension
var fullPath = assetItem.FullPath;
if (!fullPath.IsAbsolute)
{
throw new InvalidOperationException("assetItem must be an absolute path");
}
// Try to compile only if we're sure that the sources exist.
if (EnsureSourcesExist(result, assetItem))
{
Prepare(context, assetItem, assetItem.Location.GetDirectoryAndFileName(), result);
}
return result;
}
/// <summary>
/// Compiles the asset from the specified package.
/// </summary>
/// <param name="context">The context to use to compile the asset.</param>
/// <param name="assetItem">The asset to compile</param>
/// <param name="targetUrlInStorage">The absolute URL to the asset, relative to the storage.</param>
/// <param name="result">The result where the commands and logs should be output.</param>View on GitHub (pinned to 96fad776d2)