diem/diem · error · anyhow::Error
Invalid module access. Did not expect type arguments
Error message
Invalid module access. Did not expect type arguments
What it means
parse_qualified_module_access parses a string like '0x1::coin::Coin' into (ModuleId, Identifier) via parse_type_tag. A struct TypeTag with generic type parameters (e.g. '0x2::coin::Coin<0x1::sui::SUI>') is rejected because module access in test directives must reference a plain module member without generics. Non-struct type tags are rejected with the sibling 'Invalid module access' error.
Source
Thrown at language/testing-infra/transactional-test-runner/src/tasks.rs:329
}
}
}
#[derive(Debug, StructOpt)]
pub struct EmptyCommand {}
fn parse_account_address(s: &str) -> Result<AccountAddress> {
let n = move_lang::shared::parse_u128(s)
.map_err(|e| anyhow!("Failed to parse address. Got error: {}", e))?;
Ok(AccountAddress::new(n.to_be_bytes()))
}
fn parse_qualified_module_access(s: &str) -> Result<(ModuleId, Identifier)> {
match move_core_types::parser::parse_type_tag(s)? {
TypeTag::Struct(s) => {
let id = ModuleId::new(s.address, s.module);
if !s.type_params.is_empty() {
bail!("Invalid module access. Did not expect type arguments")
}
Ok((id, s.name))
}
_ => bail!("Invalid module access"),
}
}
fn parse_qualified_module_access_with_type_args(
s: &str,
) -> Result<(ModuleId, Identifier, Vec<TypeTag>)> {
match move_core_types::parser::parse_type_tag(s)? {
TypeTag::Struct(s) => {
let id = ModuleId::new(s.address, s.module);
Ok((id, s.name, s.type_params))
}
_ => bail!("Invalid module access"),
}
}View on GitHub (pinned to fc4714a8ea)
Solutions
- Remove the <...> type arguments and pass only the module/member path, e.g. 0x2::coin::Coin
- If generics are needed, check whether the directive or harness supports type args elsewhere; this parser does not
- Ensure the string parses as a struct type tag: address::module::name form
Example fix
// before //# resource-query 0x2::coin::Coin<0x1::sui::SUI> // after //# resource-query 0x2::coin::Coin
Defensive patterns
Strategy: validation
Validate before calling
fn has_no_type_args(s: &str) -> bool {
let t = move_core_types::parser::parse_type_tag(s).ok();
matches!(t, Some(TypeTag::Struct(st)) if st.type_params.is_empty())
} Type guard
fn plain_module_access(s: &str) -> Option<(ModuleId, Identifier)> {
match move_core_types::parser::parse_type_tag(s).ok()? {
TypeTag::Struct(st) if st.type_params.is_empty() =>
Some((ModuleId::new(st.address, st.module), st.name)),
_ => None,
}
} Try / catch
match parse_qualified_module_access(arg) {
Err(e) if e.to_string().contains("Did not expect type arguments") => {
bail!("strip <...> generics from module path: {}", arg)
}
other => other,
} Prevention
- Never include <...> type arguments in directives resolved by parse_qualified_module_access
- Use plain address::module::member form for resource queries
- Distinguish struct type usage (generics allowed) from module access (generics forbidden) in test files
When it happens
Trigger: Passing a qualified name with type arguments such as '0x2::coin::Coin<u64>' to a directive that expects parse_qualified_module_access; also any non-struct type tag (primitives, vectors) hits the generic 'Invalid module access' branch instead.
Common situations: Copy-pasting a generic struct type (with <...>) where a module/function path is required, e.g. in resource-query or publish-related test directives.
Related errors
- No initial command
- Invalid command. Got error {} Lines {} - {}. {}
- Failed to parse address. Got error: {}
- Module blob can't be deserialized
- CompiledModule must deserialize
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/30a6d947f66d0764.
Report an issue: GitHub.