XINCGer/Unity3DTraining · error · DescriptorValidationException
" " is not defined.
Error message
"{name}" is not defined. What it means
DescriptorPool.LookupSymbol throws DescriptorValidationException when resolving a type name referenced from a proto declaration (e.g. a field's type_name or a method's input/output type) fails. The name is looked up with protobuf's scope resolution rules (relative to the referencing descriptor's scope, then the root), and if nothing matches, the reference is reported as undefined relative to the containing descriptor.
Solutions
- Ensure all dependency .proto files of the failing file are built into the same descriptor pool before it.
- Fix the type reference: use the correct fully-qualified name with a leading dot (e.g. ".myapp.Message") or correct relative name.
- Check for typos/renames: search your .proto sources for the referenced name and update the definition or reference.
- When loading dynamically, build the full transitive dependency set (protoc --include_imports) instead of individual files.
Example fix
// before
new FieldDescriptorProto { Name = "owner", TypeName = "User", ... } // User not in pool
// after
new FieldDescriptorProto { Name = "owner", TypeName = ".myapp.User", ... } // correct FQN, User file loaded first Defensive patterns
Strategy: validation
Validate before calling
// Ensure every imported/dependent file is passed as a dependency before building:
var byName = allFiles.ToDictionary(f => f.Name);
var deps = fileProto.Dependency
.Select(d => byName.TryGetValue(d, out var fd) ? fd : throw new InvalidOperationException($"Missing dependency {d}"))
.ToList(); Try / catch
try
{
var fd = FileDescriptor.BuildFromByteString(bytes, dependencies);
}
catch (DescriptorValidationException ex) when (ex.Message.Contains("is not defined."))
{
// load missing dependency files or fix the type_name reference
} Prevention
- Use protoc --include_imports and load the full transitive descriptor set
- Always use fully-qualified type references with a leading dot in hand-built descriptors
- Run a rename refactor across all .proto files together (grep all references)
When it happens
Trigger: Building a FileDescriptor where a field's type_name (e.g. ".myapp.MissingMessage" or a relative "MissingMessage") does not match any message/enum registered in the pool — a typo in a type reference, a referenced type defined in a file that was not added to the pool, or a type removed by refactoring while references remained.
Common situations: Loading a subset of a FileDescriptorSet (missing dependency files); renaming a message in one .proto without updating references; hand-building descriptors with type_name strings that don't match actual declarations; relying on relative names without the leading dot when the type lives in a different package.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- " " is already defined (as something other than a package)…
- " " is already defined in file " ".
- Missing name.
- " " is not a valid identifier.
- Field number has already been used in " " by field " ".
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/c48b8c597625c229.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/Reflection/DescriptorPool.cs:325
// We only found the first part of the symbol. Now look for
// the whole thing. If this fails, we *don't* want to keep
// searching parent scopes.
scopeToTry.Length = dotpos + 1;
scopeToTry.Append(name);
result = FindSymbol<IDescriptor>(scopeToTry.ToString());
}
break;
}
// Not found. Remove the name so we can try again.
scopeToTry.Length = dotpos;
}
}
}
if (result == null)
{
throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined.");
}
else
{
return result;
}
}
/// <summary>
/// Struct used to hold the keys for the fieldByNumber table.
/// </summary>
private struct DescriptorIntPair : IEquatable<DescriptorIntPair>
{
private readonly int number;
private readonly IDescriptor descriptor;
internal DescriptorIntPair(IDescriptor descriptor, int number)
{
this.number = number;View on GitHub (pinned to 016f98412e)