news 2026/8/30 7:37:27

Java Agent 异常处理的可选性:从 Optional 到 CompletableFuture 的降级策略实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java Agent 异常处理的可选性:从 Optional 到 CompletableFuture 的降级策略实践

如果把 Agent 的异常处理写成传统的try-catch,大概率会在第一个真实故障面前失灵。这不是危言耸听,而是 Agent 应用与传统后端服务的本质差异决定的:Agent 的执行结果不确定、调用链不固定、外部依赖多,而且它并不是每一次失败都值得“抛出异常”。同样是一次超时,有时应该重试,有时应该降级,有时应该返回部分结果,有时应该直接快速失败。这个“根据场景选择不同异常策略”的能力,就是我们说的异常处理的可选性

这篇文章不打算只讲概念,而是把 Java 环境下实现 Agent 可选异常处理的几种常见方式拆开讲清楚:从 Optional/Result 的显式控制,到 CompletableFuture 的异步恢复,再到策略化的降级设计。你还会看到一个可以运行的完整示例,以及一套可以直接抄进项目的排查和最佳实践清单。

如果你正在做 Agent 开发、异步任务编排,或者正在排查“provider 超时未响应”“Agent 执行失败导致整条链路卡死”这类问题,这篇文章应该能帮上忙。

1. 为什么 Agent 异常处理不能只靠 try-catch

很多开发者对异常处理的理解还停留在“能捕就捕,捕不到就往上层扔”。这个思路在普通接口开发里没有问题,但在 Agent 场景里至少会遇到三个新的麻烦。

第一,Agent 的失败不一定是程序的 Bug。模型接口超时、工具服务返回 5xx、上下文过长被截断、上游限流,这些是运行常态,不是意料之外。传统 try-catch 默认把异常理解为“不应该发生的事件”,而 Agent 里恰恰相反,异常是常态的一部分。如果你把每次超时都当成重大事故来抛,系统会处于持续告警和反复重试的失控状态。

第二,Agent 的异常处理没有统一答案。同样一次“工具调用失败”,发生在用户咨询天气时可以直接返回“暂时查不到”,发生在自动化下单流程里就应该中止而不是猜一个结果。也就是说,处理策略必须可选、可配置、可替换,而不是把所有异常都塞进同一个 catch 块。

第三,Agent 调用链往往是异步和编排式的。Java 中常见的 CompletableFuture、响应式流、Agent 框架的任务编排,会让异常出现在完全不同的线程和阶段。某个子任务失败,不代表整条链路必须失败。我们需要的是“部分成功、局部补偿、选择性降级”的能力,而不是简单粗暴地 throw。

所以,Agent 异常处理的核心不是“捕获”,而是决策。可选性就是在异常发生后,系统能根据场景选择最合适的策略。

2. 异常处理的可选性到底是什么

“可选性”这个词听起来抽象,放进代码里就很具体。它至少包含三层含义。

第一层是处理方式可选。对于一个失败,系统可以选择重试、忽略、降级、终止、转人工、返回默认值,等等。不同异常类型、不同业务状态,可以选择不同策略。

第二层是处理粒度可选。可以针对整个 Agent 任务做处理,也可以细化到单次模型调用、单次工具调用、单步推理。粒度越细,系统的容错能力越强,但实现成本也越高。

第三层是策略本身可配置。生产环境中,运维和研发往往需要在不改代码的情况下调整超时时间、重试次数、降级开关。可选性的另一个面向,是把异常策略变成配置而不是硬编码逻辑。

我们用一张表对比传统异常处理和 Agent 可选异常处理:

维度传统 try-catchAgent 可选异常处理
异常定位认为是 Bug认为是运行常态
处理方式捕获、包装、抛出选择、恢复、降级、终止
失败粒度方法或接口子任务、工具调用、模型调用
上下文依赖较弱强,依赖业务场景与执行进度
可配置性
代表结构try-catch-finallyOptional、Result、重试策略、降级策略

这张表想说明一个判断:“可选性”不是另一种语法,而是把异常处理从“语法层”提升到“策略层”。理解了这一层,再去看代码实现,思路就会清晰很多。

3. Java 中合法的异常处理结构:先打好语法地基

在进入 Agent 场景之前,值得先把 Java 本身提供的异常处理结构梳理一遍。很多 Agent 框架的异常处理底层就是这些基础语法,只是外面包了一层策略。

3.1 try-catch-finally

最基础的结构。finally 块保证资源清理或必要收尾工作执行,即使异常被抛出或捕获。

try { String result = agentClient.chat(prompt); return result; } catch (AgentTimeoutException e) { log.warn("agent timeout, use fallback"); return fallback(prompt); } catch (AgentExecutionException e) { log.error("agent execution failed", e); throw new BizException("AGENT_EXEC_ERROR", e); } finally { trace.endSpan(); }

这是 Java 中最合法的异常处理结构之一,但它的问题也很明显:一旦异常场景变多,catch 块会逐渐膨胀,而且策略是写死的。

3.2 多异常捕获

Java 7 开始支持|合并多个异常类型。适合异常处理逻辑相同的情况。

catch (AgentTimeoutException | RateLimitException e) { // 都当作可重试异常处理 return retryOrFallback(prompt, e); }

3.3 try-with-resources

适合需要自动关闭资源的场景。Agent 开发中比较典型的场景是 HTTP 客户端、数据库连接、文件会话。

try (AgentSession session = new AgentSession(userId)) { return session.run(prompt); }

这个结构不仅合法,而且避免了手动关闭资源漏写的问题。Agent SDK 如果提供了 AutoCloseable 的会话对象,推荐优先使用。

3.4 方法声明 throws

把异常传递给调用方,由上层决定策略。适合“当前层无法判断业务语义”的情况。

public AgentResult run(AgentRequest request) throws AgentExecutionException { // 具体执行逻辑 }

需要说明的是,throws不是逃避处理,而是在架构上把决策权上移。这在 Agent 编排中非常常见:底层工具不知道上层业务期望什么,上层才清楚该重试还是放弃。

这些基础语法,任何一种 Java 应用都绕不开。但在 Agent 场景中,我们还需要两个额外的能力:用返回值表达失败,以及在异步任务中恢复

4. 用 Optional 和 Result 把异常变成可选值

Java 8 引入Optional后,很多开发者开始用它表达“可能没有值”。但 Optional 在异常处理中的价值往往被低估:它让“异常”从控制流变成数据流。

考虑一个最简单的场景:从工具服务读取配置,读取失败时返回空配置,而不是抛异常。

public Optional<AgentConfig> loadConfig(String agentId) { try { AgentConfig config = configClient.get(agentId); return Optional.ofNullable(config); } catch (IOException e) { log.warn("load config failed, agentId={}, fallback to empty", agentId, e); return Optional.empty(); } }

调用方可以这样使用:

AgentConfig config = loadConfig(agentId) .orElseGet(() -> defaultConfig(agentId));

这种写法的好处是:失败不再中断主流程,而是变成调用方可以选用的空值。Optional 让异常可以是“可选的”。

不过 Optional 有一个局限:它只能表达“有或没有”,无法表达“为什么没有”。如果下游故障的排查需要错误原因,Optional 就不够用。这时更推荐引入一个轻量级的 Result 类型。

public sealed interface Result<T> { record Success<T>(T value) implements Result<T> {} record Failure<T>(String code, String message, Throwable cause) implements Result<T> {} }

这个结构在 Java 21 下可以正常编译。如果你的项目还停留在 Java 8,也可以用传统 abstract class 或直接复用第三方库里的 Either 类型。

使用示例:

public Result<AgentResponse> execute(AgentTask task) { try { AgentResponse response = agentExecutor.run(task); return new Result.Success<>(response); } catch (AgentTimeoutException e) { return new Result.Failure<>("TIMEOUT", "agent execute timeout", e); } catch (Exception e) { return new Result.Failure<>("UNKNOWN", e.getMessage(), e); } }

调用方可以根据 Result 的情况选择策略:

Result<AgentResponse> result = execute(task); if (result instanceof Result.Success<AgentResponse> success) { return success.value(); } Result.Failure<AgentResponse> failure = (Result.Failure<AgentResponse>) result; if ("TIMEOUT".equals(failure.code())) { return retryLater(task); } return fallback(task);

看到这里你可能会问:这不就是把异常换成返回值吗?是的。但关键在于,返回值天然支持多个分支决策,而且不会像异常那样打断栈帧语义。对于 Agent 这种“大部分子任务失败可以被局部补偿”的场景,用返回值表达失败往往比异常更合适。

5. CompletableFuture 异步编程中的异常处理与可选恢复

Agent 开发中,异步编排是绕不开的。CompletableFuture 提供了几个关键的异常处理方法:

  • exceptionally:为异常提供一个恢复值。
  • handle:不管成功还是失败,都返回一个新值。
  • whenComplete:感知结果但不改变结果。
  • completeExceptionally:手动让 future 以异常完成。

其中exceptionally是“可选异常处理”最直接的体现:它把异常转换为一个可选的替代结果。

下面这段代码模拟了一个 Agent 并发调用两个模型的场景,一个失败时用另一个的结果兜底。

import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class AgentAsyncDemo { public static void main(String[] args) { CompletableFuture<String> modelA = CompletableFuture .supplyAsync(() -> callModel("model-a")) .exceptionally(ex -> { System.out.println("model-a 调用失败: " + ex.getMessage()); return null; }); CompletableFuture<String> modelB = CompletableFuture .supplyAsync(() -> callModel("model-b")) .exceptionally(ex -> { System.out.println("model-b 调用失败: " + ex.getMessage()); return null; }); CompletableFuture<String> result = modelA .thenCombine(modelB, (a, b) -> { if (a != null) { return "A: " + a; } if (b != null) { return "B: " + b; } throw new IllegalStateException("两个模型都失败了"); }) .exceptionally(ex -> "fallback: " + ex.getMessage()); System.out.println(result.join()); } private static String callModel(String modelName) { if (modelName.equals("model-a")) { throw new RuntimeException("timeout"); } return "ok from " + modelName; } }

运行结果大致如下:

model-a 调用失败: java.lang.RuntimeException: timeout A: null

这里我们要注意一个容易踩的坑:exceptionally返回null之后,后续thenCombine里确实可以通过判空来降级,但如果你在thenCombine中抛出了新异常,外层还需要再包一层exceptionally。也就是说,异步异常处理的每个阶段都可以重新产生失败,可选恢复不是一个终点,而是一条链

更稳妥的做法是,用一个单独的handle来统一处理成功和失败:

CompletableFuture<String> safeResult = modelA .handle((value, ex) -> { if (ex != null) { log.warn("model-a failed", ex); return modelB.join(); } return value; });

在 Agent 引擎开发中,超时控制往往比异常捕获更关键。一个常见错误写法是单方面依赖下游 SDK 的 timeout 参数,但整个编排链路的超时没有兜底。下面这段代码演示了为 future 设置超时并返回默认值:

CompletableFuture<String> future = CompletableFuture .supplyAsync(() -> callModel("model-a")); String result = future .completeOnTimeout("default-result", 5, TimeUnit.SECONDS) .join();

Java 9 引入的completeOnTimeout让“超时即可选降级”变得很简洁。如果你的项目还在 Java 8,需要换成orTimeoutexceptionally

String result = future .orTimeout(5, TimeUnit.SECONDS) .exceptionally(ex -> "default-result") .join();

这两种写法都是合法的 Java 异步异常处理手段。关键不在于选哪个 API,而在于:每个异步步骤都要有一个明确的、可选的失败出口

6. 环境准备与前置条件

如果想把上面的示例跑起来,建议准备以下环境:

  • JDK 17 或更高版本,示例中使用了 Java 21 的 sealed interface 语法,如果使用 JDK 17,可以把 record 和 sealed 简单改成普通 class。
  • Maven 3.8+ 或 Gradle 7+。
  • Spring Boot 3.x,用于演示配置文件与策略注入。不强制,但本文的完整示例用 Spring Boot 承载。
  • 一个可用的 Agent 执行器,可以是自研实现,也可以封装第三方 SDK。如果只是验证异常处理逻辑,可以直接使用 Mock 数据代替真实模型调用。

版本方面,以实际项目当前依赖为准。本文核心是通用思路,不依赖某个具体 Agent 框架的内部 API。

Maven 依赖建议:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

如果你确实在集成某个 Agent 框架,再自行补充对应 SDK 依赖。下面是完整示例的核心代码。

7. 完整示例:一个具有可选异常处理能力的 Agent 执行器

我把上面的概念合并成一个可运行的最小工程。目标是实现一个具备以下能力的 Agent 执行器:

  1. 模型调用超时可选处理。
  2. 工具调用失败可选降级。
  3. 重试次数可配置。
  4. 失败后可以选择返回默认结果、抛出异常或进入人工队列。

这里为了演示,我模拟了一个 Agent 执行过程:第一步调用模型,第二步调用一个工具接口,任意一步失败时进入策略选择。

7.1 项目结构

agent-demo/ ├── pom.xml └── src/main/java/com/example/agentdemo/ ├── AgentDemoApplication.java ├── core/ │ ├── Result.java │ ├── AgentExecutorService.java │ └── FallbackStrategy.java └── web/ └── AgentController.java

7.2 定义 Result 类型

package com.example.agentdemo.core; public sealed interface Result<T> { record Success<T>(T value) implements Result<T> { } record Failure<T>(String code, String message, Throwable cause) implements Result<T> { } static <T> Result<T> ok(T value) { return new Success<>(value); } static <T> Result<T> fail(String code, String message, Throwable cause) { return new Failure<>(code, message, cause); } }

这个类型是“可选异常”的载体。Agent 执行过程中的任何异常都可以先包装成 Result,再由上层决定如何处理。

7.3 定义可选处理策略

package com.example.agentdemo.core; @FunctionalInterface public interface FallbackStrategy<T> { T apply(Result.Failure<T> failure); }

这个接口允许调用方传入不同的降级函数。在实际工程中,你可以为它提供多个实现,例如:

  • 返回默认值。
  • 重新执行一次简化流程。
  • 写入人工处理队列。
  • 抛出业务异常。

7.4 核心 Agent 执行服务

package com.example.agentdemo.core; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @Service public class AgentExecutorService { private static final Logger log = LoggerFactory.getLogger(AgentExecutorService.class); private final ExecutorService executor = Executors.newCachedThreadPool(); public <T> Result<T> executeWithFallback( AgentTask<T> task, Duration timeout, FallbackStrategy<T> fallbackStrategy ) { CompletableFuture<Result<T>> future = CompletableFuture .supplyAsync(task::run, executor) .handle((value, ex) -> { if (ex != null) { log.warn("agent task failed, ex={}", ex.getMessage()); return Result.<T>fail("TASK_FAILED", ex.getMessage(), ex); } return Result.ok(value); }); try { Result<T> result = future.get(timeout.toMillis(), java.util.concurrent.TimeUnit.MILLISECONDS); if (result instanceof Result.Success<T> success) { return Result.ok(success.value()); } Result.Failure<T> failure = (Result.Failure<T>) result; if (fallbackStrategy != null) { T fallbackValue = fallbackStrategy.apply(failure); return Result.ok(fallbackValue); } return failure; } catch (java.util.concurrent.TimeoutException e) { future.cancel(true); log.warn("agent task timeout after {} ms", timeout.toMillis()); if (fallbackStrategy != null) { Result.Failure<T> failure = Result.fail("TIMEOUT", "agent task timeout", e); return Result.ok(fallbackStrategy.apply(failure)); } return Result.fail("TIMEOUT", "agent task timeout", e); } catch (Exception e) { log.error("agent task interrupted", e); return Result.fail("INTERRUPTED", e.getMessage(), e); } } @FunctionalInterface public interface AgentTask<T> { T run(); } }

这个服务的关键点在于:

  • handle把同步异常转换成了 Result。
  • future.get(timeout)实现了整体超时控制。
  • fallbackStrategy让调用方传入不同的失败恢复策略,这就是“可选性”。

7.5 使用示例:模拟模型调用超时

package com.example.agentdemo.web; import com.example.agentdemo.core.AgentExecutorService; import com.example.agentdemo.core.Result; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.time.Duration; @RestController @RequestMapping("/agent") public class AgentController { private final AgentExecutorService executorService; public AgentController(AgentExecutorService executorService) { this.executorService = executorService; } @GetMapping("/run") public String run() { AgentExecutorService.AgentTask<String> task = () -> { // 模拟模型调用:有一定概率超时或失败 if (System.currentTimeMillis() % 3 == 0) { throw new RuntimeException("model provider not respond in time"); } return "task completed"; }; // 可选策略1:失败时返回默认值 Result<String> result = executorService.executeWithFallback( task, Duration.ofSeconds(2), failure -> "fallback-default" ); // 可选策略2:失败时返回错误码,不抛异常 if (result instanceof Result.Failure<String> failure) { return "error code: " + failure.code(); } return result.value(); } }

7.6 配置示例

Spring Boot 中可以把超时时间、重试次数等参数配置化:

agent: execution: timeout-ms: 3000 max-retry: 2 fallback-enabled: true fallback-value: "sorry, please try again later"
@ConfigurationProperties(prefix = "agent.execution") @Component public class AgentExecutionProperties { private long timeoutMs = 3000; private int maxRetry = 2; private boolean fallbackEnabled = true; private String fallbackValue = "sorry"; // getter/setter 省略 }

这样,选择哪种异常处理策略,从代码层上浮到了配置层。线上修改降级开关时,不需要重新发布应用,这也是可选性在工程层面的重要体现。

8. 运行结果与效果验证

启动 Spring Boot 应用后,访问:

http://localhost:8080/agent/run

多次刷新,因为每次调用有三分之一的概率抛出“model provider not respond in time”,你会看到两种输出:

task completed

fallback-default

判断成功的标准很简单:

  1. 应用进程不崩溃。
  2. 超时或异常不会导致接口 500。
  3. 返回值要么是真实结果,要么是 fallback 值。
  4. 日志中能看到agent task failedagent task timeout的告警信息。

如果想验证失败策略为“抛出业务异常”的场景,可以在 FallbackStrategy 中直接抛异常:

Result<String> result = executorService.executeWithFallback( task, Duration.ofSeconds(2), failure -> { throw new BizException("AGENT_UNAVAILABLE", failure.message()); } );

这样接口会以业务异常终止,而不是静默降级。可选性意味着你有权选择“不降级”

如果运行失败,建议按以下顺序排查:

  • 检查端口是否被占用。
  • 检查 Spring Boot 是否成功启动。
  • 检查是否添加了@ConfigurationProperties的依赖支持,如果缺失,可以使用@Value代替。
  • 检查 JDK 版本是否支持 sealed interface,如果不支持,把Result改成普通 interface 或 class。

9. 常见问题与排查思路

问题现象可能原因排查方式解决方案
接口长时间不返回未设置整体超时查看线程栈,确认阻塞点使用 future.get(timeout) 统一超时
模型调用失败后仍继续执行缺少失败状态检查查看日志,确认 Result 是否被忽略在关键步骤强制检查 Result
重试风暴,导致下游被打挂重试策略不加限制查看调用链和重试日志限制重试次数,启用退避策略
降级后返回错误结果fallback 逻辑与业务语义不匹配检查降级值来源为不同场景配置不同 fallback
本地运行正常,线上超时频繁线上延迟更大对比两端耗时分布调大超时时间,或改为异步回调
异常被吞掉,无法定位只在 handle 中打印 message检查完整堆栈日志记录 cause 与 context 信息
多个可选策略相互冲突策略优先级不明确梳理代码分支用配置中心统一控制策略开关

排查 Agent 异常问题,第一原则是把日志和状态记录下来,而不是先改代码。很多看似复杂的故障,日志里其实已经给出了答案。

10. 最佳实践与工程建议

结合前面这些示例,我在实际项目中会坚持以下几件事。

第一,优先用返回值表达业务可预期失败,用异常表达不可预期失败。模型超时、工具返回空、上游限流,这些应该走 Result 或 Optional 分支;代码 Bug、配置错误、序列化异常,才应该抛出异常。这个边界决定了整个系统的容错质量。

第二,每个异步任务都要有超时兜底。CompletableFuture 的orTimeoutcompleteOnTimeout,或者显式get(timeout),至少选一个。没有超时的异步编排,在 Agent 场景里就像没有保险丝的电路。

第三,把异常处理策略配置化。超时毫秒数、重试次数、fallback 开关、人工兜底开关,尽可能放到配置中心。Agent 系统的运行环境变化很快,今天适用的策略,下周可能就不适用了。

第四,为失败设计可观测性。在每次异常处理时记录:失败了哪一步、选择了什么策略、消耗了多少重试次数、降级结果是否命中。这些数据能为后续调优提供依据。

第五,注意幂等性。Agent 的重试可能造成重复消息或重复操作。建议在多次重试之间使用幂等键,尤其是涉及支付、下单、发送消息等场景时,不要假设重试只会发生一次。

第六,安全边界不能因为降级而放松。异常处理的可选性不意味着你可以随意绕过权限校验。模型调用失败后的 fallback 如果接入了非预期系统,必须走同样的授权流程。

11. 总结与后续学习方向

这篇文章围绕“Agent 异常处理之可选性”展开,核心判断是:Agent 的异常处理不应该只有“捕获并抛出”一条路,而应该是一套可选的策略集合。理解 Optional 和 Result 如何把异常变成值,理解 CompletableFuture 如何在异步链路中恢复,再配合一个可配置的降级入口,基本就能支撑大多数 Agent 工程需求。

如果你正在做 Agent 框架的二次开发,接下来值得继续深入的方向包括:重试退避算法的选取、分布式链路追踪在 Agent 调用链里的落地、熔断器模式在工具调用层的应用,以及如何把 LLM 返回格式错误纳入异常处理体系。

先把手头的最小示例跑通,再逐步把策略接入真实业务,这个顺序比直接抄一个大而全的框架代码要稳妥得多。建议收藏备用,后面踩坑的时候可以再翻回来对照。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 7:36:35

人形机器人核心技术栈拆解与仿真开发入门指南

这次让人形机器人赛道重新成为焦点的&#xff0c;不是某款新机型的演示视频&#xff0c;而是一笔规模惊人的融资&#xff1a;孙正义被曝以约60亿美元级别押注1X Technologies。这个消息一出&#xff0c;“1X”和“人形机器人”几乎同时冲上技术社区热搜&#xff0c;很多人的第一…

作者头像 李华
网站建设 2026/8/30 7:36:27

统一多模态线稿上色:从架构原理到PyTorch实现解析

OmniColor 这个名称对应一个非常具体的研究问题&#xff1a;如何把文本、颜色提示、参考图等多种条件输入统一到同一个线稿上色框架中。线稿上色是图像生成里的经典任务&#xff0c;输入只有一张黑白线稿&#xff0c;模型要补出合理的颜色&#xff1b;但颜色组合几乎无限&#…

作者头像 李华
网站建设 2026/8/30 7:34:36

从HashMap到Kafka:Java面试底层原理深度解析

1. 八股文的本质与局限&#xff1a;背下来的答案&#xff0c;始终不是你的先聊几句大实话。我面过不少候选人&#xff0c;也陪身边朋友模拟过很多轮面试。有一种情况特别常见&#xff1a;简历上写着“熟悉Java集合源码”&#xff0c;HashMap的put流程背得一字不差&#xff0c;但…

作者头像 李华
网站建设 2026/8/30 7:34:26

SpringBoot3+Vue2前后端分离CMS内容管理系统实战解析

简介&#xff1a;这是一套面向Java与前端开发者的内容管理系统&#xff08;CMS&#xff09;实战项目资源&#xff0c;适用于SpringBoot与Vue技术栈的中高级学习者及全栈工程师&#xff0c;旨在解决传统单体CMS开发效率低、维护难、前后端耦合深等痛点。资源采用SpringBoot3构建…

作者头像 李华
网站建设 2026/8/30 7:33:34

STM32H573 Secure Manager报错-129:PSA密钥生成权限排查与解决

STM32H573 Secure Manager 踩坑实录&#xff1a;psa_generate_key() 返回 -129 的排查全过程 先说我遇到的现象&#xff0c;再带你把这块硬骨头从头到尾啃一遍。我在 STM32H573 上用 Secure Manager 做密钥管理&#xff0c;代码里调用 psa_generate_key() 想生成一个 volatil…

作者头像 李华