DEBUG.WIKI
雨云;给项目一台云服务器
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →

Gradle 可选文件输入仍报 has no value,先对比配置缓存开关

Gradle 9.7.0-milestone-1 中,运行时注册的 optional 文件输入接收空 Provider 时,配置缓存路径仍可能取值失败。先保留输入语义,局部关闭缓存。

任务已经把输入标成 optional(),Gradle 仍报 Cannot query the value of this property because it has no value available。若相同任务关闭 configuration cache 就能运行,先检查空 Provider 在配置缓存路径中的处理,别急着给它填一个不存在的文件。

明确出现过问题的版本是 Gradle 9.7.0-milestone-1,输入通过运行时 API 注册,形状如下:

def optionalSource = objects.fileProperty()

tasks.register("inspectInput") {
    inputs.files(optionalSource).optional().withPropertyName("inputFiles")
    def out = layout.buildDirectory.file("out.txt")
    outputs.file(out)
    doLast {
        out.get().asFile.text = "done"
    }
}

这个最小任务会写入可再生的 build/out.txt,应在独立测试项目中使用;不要覆盖项目已有的同名产物。动作与输出让任务真正进入输入指纹计算,而不是作为没有动作的任务被跳过。

这里 optionalSource 没有值。它与“Provider 有值,但该路径上的文件不存在”不同;后者还要按文件输入验证和业务要求处理。

保持任务相同,只改变缓存选项

在可以运行该任务的本机测试环境,对比原入口:

./gradlew inspectInput --configuration-cache
./gradlew inspectInput --no-configuration-cache

将任务名换成实际任务。这些命令会运行任务动作,先确认它是否会打包、上传或改写文件,不能把它们当纯只读诊断。

如果前者报空值、后者正常,且输入确实由 inputs.files(provider).optional() 注册,可把问题限定到该路径。若两者都失败,继续查 Provider 是不是在其他地方被提前 get(),或插件要求该输入实际上必须存在。

临时关闭该入口的配置缓存

需要继续工作时,先在受影响的构建入口加 --no-configuration-cache。这样会放弃该次配置缓存复用,增加配置耗时,但不用伪造输入,也不改变任务处理“没有可选文件”的业务含义。保留原配置和触发记录,后续在兼容的正式版本上复查。

不要把 org.gradle.configuration-cache.problems=warn 当通用修复。它不能保证一个没有值的 Provider 可以被正确取值,也可能允许其他不兼容状态继续运行。

插件作者若考虑将缺失文件转换成空文件集合,应先检查整个输入契约:没有值、空集合和真实空文件是否在任务动作中等价,是否影响缓存键和 up-to-date 判断。不要仅为消除这一行异常创建一个占位文件,然后让任务误以为上游产物已经存在。

修复验收需要覆盖可选值缺失和存在两种情况。缓存打开时,首次运行与缓存复用都要符合预期;上游文件从有到无、从无到有时,任务不能继续使用过期结果。没有验证相应发布版前,不能仅因问题关闭就移除临时缓存开关。