Unity-Technologies/UnityCsReference · error · ArgumentException
Incorrect file extension: {prefabAssetPath}. Must be '.prefa
Error message
Incorrect file extension: {prefabAssetPath}. Must be '.prefab' What it means
Thrown by PrefabStageUtility.OpenPrefab when prefabAssetPath does not end with '.prefab' (case-insensitive). The prefab system only operates on assets with the .prefab extension; any other extension is rejected at the validation boundary.
Source
Thrown at Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs:96
var prefabStageMode = openedFromInstance != null ? PrefabStage.Mode.InContext : PrefabStage.Mode.InIsolation;
return OpenPrefab(prefabAssetPath, openedFromInstance, prefabStageMode, changeTypeAnalytics);
}
public static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode)
{
return OpenPrefab(prefabAssetPath, openedFromInstance, prefabStageMode, StageNavigationManager.Analytics.ChangeType.EnterViaUnknown);
}
internal static PrefabStage OpenPrefab(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode, StageNavigationManager.Analytics.ChangeType changeTypeAnalytics)
{
if (string.IsNullOrEmpty(prefabAssetPath))
throw new ArgumentNullException(nameof(prefabAssetPath));
if (openedFromInstance != null && !PrefabUtility.IsPartOfPrefabInstance(openedFromInstance))
throw new ArgumentException("GameObject must be part of a Prefab instance, or null.", nameof(openedFromInstance));
if (!prefabAssetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase))
throw new ArgumentException("Incorrect file extension: " + prefabAssetPath + ". Must be '.prefab'", nameof(prefabAssetPath));
if (AssetDatabase.LoadMainAssetAtPath(prefabAssetPath) == null)
throw new ArgumentException("Prefab not found at path " + prefabAssetPath, nameof(prefabAssetPath));
return OpenPrefabMode(prefabAssetPath, openedFromInstance, prefabStageMode, changeTypeAnalytics);
}
static PrefabStage GetExistingPrefabStage(string prefabAssetPath, GameObject openedFromInstance, PrefabStage.Mode prefabStageMode)
{
var stageHistory = StageNavigationManager.instance.stageHistory;
for (int i = 1; i < stageHistory.Count; i++)
{
var prefabStage = stageHistory[i] as PrefabStage;
if (prefabStage != null && prefabStage.assetPath == prefabAssetPath)
{
// If PrefabStage.Mode did not match on existing PrefabStage we do not reuse the stage
// so we create a new PrefabStage with the correct mode
if (prefabStage.mode == prefabStageMode)View on GitHub (pinned to 225b0fbdb5)
Solutions
- Ensure the path string ends with '.prefab' (case-insensitive).
- Construct paths using Path.Combine and explicitly append '.prefab'.
- Validate with prefabAssetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase) before calling.
Example fix
// before
PrefabStageUtility.OpenPrefab("Assets/MyObject", null, mode);
// after
PrefabStageUtility.OpenPrefab("Assets/MyObject.prefab", null, mode); Defensive patterns
Strategy: validation
Validate before calling
bool IsValidPrefabPath(string path)
{
return !string.IsNullOrEmpty(path) && path.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase);
} Prevention
- Always build prefab asset paths with an explicit '.prefab' suffix.
- Use Path.Combine and append '.prefab' rather than relying on string concatenation.
When it happens
Trigger: Passing a path with .prefabVariant, .asset, .mat, or no extension. Typo in the path extension. Constructed paths that drop the extension during string manipulation.
Common situations: Path built via Path.GetFileNameWithoutExtension without re-appending '.prefab'. Mixing up prefab asset paths with ScriptableObject '.asset' paths. Cross-platform path separators causing the EndsWith check to miss.
Related errors
- path is null or empty
- Given path is not valid: '{path}'
- Prefab Mode: GameObject must be part of a Prefab instance, o
- Prefab Mode: The 'openedFromInstance' GameObject '{go.name}'
- Cannot save as new prefab using the same path
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/1c7b8c17b2b972b9.
Report an issue: GitHub.