在Rust/Anchor函数返回时如何将自定义错误转为ProgramError类型?
问题描述
使用Rust和Anchor开发Solana程序时,通过#[error_code]宏定义了自定义错误枚举ErrorCode,但在#[program]代码块中尝试用.into()将自定义错误转为ProgramError时,触发如下报错:
the trait bound
anchor_lang::prelude::ProgramError: From<ErrorCode>is not satisfied the following other types implement traitFrom<T>:
<anchor_lang::prelude::ProgramError as From>
<anchor_lang::prelude::ProgramError as From<anchor_lang::error::Error>>
<anchor_lang::prelude::ProgramError as Fromstd::io::Error>
<anchor_lang::prelude::ProgramError as From> required forErrorCodeto implementInto<anchor_lang::prelude::ProgramError>
相关代码片段
程序主逻辑
#[program] pub mod solana_twitter { use super::*; pub fn send_tweet( ctx: Context<SendTweet>, topic: String, content: String, ) -> ProgramResult { let tweet: &mut Account<Tweet> = &mut ctx.accounts.tweet; let author: &Signer = &ctx.accounts.author; let clock: Clock = Clock::get().unwrap(); if topic.chars().count() > 50 { return Err(ErrorCode::TopicTooLong.into()); } if content.chars().count() > 280 { return Err(ErrorCode::ContentTooLong.into()); } tweet.author = *author.key; tweet.timestamp = clock.unix_timestamp; tweet.topic = topic; tweet.content = content; Ok(()) } }
自定义错误枚举
#[error_code] pub enum ErrorCode { #[msg("The provided topic should be 50 characters long maximum.")] TopicTooLong, #[msg("The provided content should be 280 characters long maximum.")] ContentTooLong, }
解决方案
Anchor的#[error_code]宏并未为自定义错误实现Into<ProgramError> trait,可通过以下两种方式完成转换:
方式1:用ProgramError::Custom包裹错误码
Anchor会自动为标注#[error_code]的枚举分配唯一u32错误码,直接将变体转为u32后传入ProgramError::Custom即可:
if topic.chars().count() > 50 { return Err(ProgramError::Custom(ErrorCode::TopicTooLong as u32)); } if content.chars().count() > 280 { return Err(ProgramError::Custom(ErrorCode::ContentTooLong as u32)); }
方式2:使用Anchor的IntoProgramError trait
- 先在代码顶部导入该trait:
use anchor_lang::error::IntoProgramError;
- 修改错误返回逻辑:
if topic.chars().count() > 50 { return Err(ErrorCode::TopicTooLong.into_program_error()); } if content.chars().count() > 280 { return Err(ErrorCode::ContentTooLong.into_program_error()); }
原理说明
Anchor的#[error_code]宏会为枚举实现AnchorError trait,处理错误码和错误信息逻辑,但未直接实现Into<ProgramError>。IntoProgramError是Anchor专门提供的转换trait,而ProgramError::Custom是Solana SDK承载自定义错误码的标准变体,两种方式都能完成正确转换。
内容的提问来源于stack exchange,提问作者Rafael Moreira

