stride3d/stride · error · ArgumentException

The relativePath argument is null or empty

Error message

The relativePath argument is null or empty

What it means

The protected helper GetAbsolutePath combines a relative path with the parent directory of the asset's FullPath to produce an absolute on-disk path. It guards against a null or empty UFile argument by throwing ArgumentException, since combining an empty path is meaningless.

Solutions

  1. Ensure the asset's source path property (e.g. Yolo/Source) is set before compilation.
  2. Guard with string.IsNullOrEmpty(relativePath) in the compiler and log a proper error instead of passing it through.
  3. Fix asset deserialization so missing path fields get a default or are reported as a validation error.
  4. If the path should be optional, skip GetAbsolutePath when empty instead of calling it.

Example fix

// before
var abs = GetAbsolutePath(assetItem, asset.Source); // Source is empty UFile
// after
if (!string.IsNullOrEmpty(asset.Source))
{
    var abs = GetAbsolutePath(assetItem, asset.Source);
}
else
{
    logger.Error($"Asset {assetItem.Location} is missing its source path.");
}
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(asset.Source))
{
    logger.Error($"Asset {assetItem.Location} has no source path set.");
    return;
}
var abs = GetAbsolutePath(assetItem, asset.Source);

Type guard

static bool HasSourcePath(UFile relativePath) => !string.IsNullOrEmpty(relativePath);

Try / catch

try
{
    var abs = GetAbsolutePath(assetItem, asset.Source);
}
catch (ArgumentException ex)
{
    logger.Error($"Missing source path for asset {assetItem.Location}: {ex.Message}");
}

Prevention

When it happens

Trigger: Calling GetAbsolutePath(assetItem, relativePath) from a custom asset compiler with an uninitialized or empty UFile — e.g. a source/import path field on the asset was never set (default UFile is empty string).

Common situations: Asset YAML missing the expected source path field so it deserializes to an empty UFile; user cleared the 'Source' field in the editor; a compiler reading the wrong (unused) property as its relative path.

Related errors


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

Appendix: source

Thrown at sources/assets/Stride.Core.Assets/Compiler/AssetCompilerBase.cs:85

    /// <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>
    protected abstract void Prepare(AssetCompilerContext context, AssetItem assetItem, string targetUrlInStorage, AssetCompilerResult result);

    /// <summary>
    /// Returns the absolute path on the disk of an <see cref="UFile"/> that is relative to the asset location.
    /// </summary>
    /// <param name="assetItem">The asset on which is based the relative path.</param>
    /// <param name="relativePath">The path relative to the asset path that must be converted to an absolute path.</param>
    /// <returns>The absolute path on the disk of the <paramref name="relativePath"/> argument.</returns>
    /// <exception cref="ArgumentException">The <paramref name="relativePath"/> argument is a null or empty <see cref="UFile"/>.</exception>
    protected static UFile GetAbsolutePath(AssetItem assetItem, UFile relativePath)
    {
        if (string.IsNullOrEmpty(relativePath)) throw new ArgumentException("The relativePath argument is null or empty");
        var assetDirectory = assetItem.FullPath.GetParent();
        var assetSource = UPath.Combine(assetDirectory, relativePath);
        return assetSource;
    }

    /// <summary>
    /// Ensures that the sources of an <see cref="Asset"/> exist.
    /// </summary>
    /// <param name="result">The <see cref="AssetCompilerResult"/> in which to output log of potential errors.</param>
    /// <param name="assetItem">The asset to check.</param>
    /// <returns><c>true</c> if the source file exists, <c>false</c> otherwise.</returns>
    /// <exception cref="ArgumentNullException">Any of the argument is <c>null</c>.</exception>
    private static bool EnsureSourcesExist(AssetCompilerResult result, AssetItem assetItem)
    {
        ArgumentNullException.ThrowIfNull(result);
        ArgumentNullException.ThrowIfNull(assetItem);

        var collector = new SourceFilesCollector();

View on GitHub (pinned to 96fad776d2)