False-positive cache-control records in report

I’m observing discrepancy in my reports specific to cache-control response headers.
Some resources are listed as “FAILED - (No max-age or expires)” in Cache section of the report, but I do see this header displayed in Details section for the given sub-request
Sample report:

Following resource is listed as “FAILED - (No max-age or expires)”:

FAILED - (No max-age or expires) - https://www.toyota.com/imgix/content/homepage/img/explore/ToyotaRacing.png?w=552&dpr=1&q=80&fm=jpg&lossless=false&fit=max&cs=strip&bg=fff&

But here is what is listed in the Details section:

[code]Request 11: https://www.toyota.com/imgix/content/homepage/img/explore/ToyotaRacing.png?w=552&dpr=1&q=80&fm=jpg&lossless=false&fit=max&cs=strip&bg=fff&
URL: https://www.toyota.com/imgix/content/homepage/img/explore/ToyotaRacing.png?w=552&dpr=1&q=80&fm=jpg&lossless=false&fit=max&cs=strip&bg=fff&
Host: www.toyota.com
Error/Status Code: 200
Priority: Low
Protocol: HTTP/2
HTTP/2 Stream: 21, weight 147, depends on 19, EXCLUSIVE
Initiated By: https://www.toyota.com/?removeEnsighten=true line 2202
Client Port: 65068
Request Start: 1.060 s
Time to First Byte: 79 ms
Content Download: 27 ms
Bytes In (downloaded): 36.3 KB
Uncompressed Size: 35.9 KB
Bytes Out (uploaded): 0.1 KB
Request Headers:

:method: GET
:authority: www.toyota.com
:scheme: https
:path: /imgix/content/homepage/img/explore/ToyotaRacing.png?w=552&dpr=1&q=80&fm=jpg&lossless=false&fit=max&cs=strip&bg=fff&
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 PTST/396
accept: image/webp,image/apng,image/,/*;q=0.8
referer: https://www.toyota.com/?removeEnsighten=true
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.8
Response Headers:

:status: 200
content-type: image/jpeg
content-length: 36802
cache-control: public,max-age=604800
last-modified: Tue, 26 Sep 2017 17:10:51 GMT
server: imgix-fe
accept-ranges: bytes
date: Wed, 11 Oct 2017 22:09:11 GMT
x-content-type-options: nosniff
x-served-by: cache-lax8626-LAX, cache-iad2123-IAD
age: 1028091
x-cache: Hit from cloudfront
via: 1.1 cf6dfc066230dcf69540e8c3f8d6f9de.cloudfront.net (CloudFront)
x-amz-cf-id: K-rD5hX3vwu8Xtvf-m3qeBUZxesQxKPwAJe0UFl7uoJ-hKuXRnF3sw==

There are like ten resources like this listed in that report.

In addition to that, I checked the response code in “repeat View”, and found that it is 304 - means that resource IS actually cached:

:status: 304 date: Mon, 16 Oct 2017 20:46:19 GMT cache-control: public,max-age=604800 server: imgix-fe x-content-type-options: nosniff x-served-by: cache-lax8626-LAX, cache-iad2123-IAD age: 1028111 x-cache: Hit from cloudfront via: 1.1 98dbec6ba78c561cf37410a3bbd19a4e.cloudfront.net (CloudFront) x-amz-cf-id: yZXWoDUdEUbaVQym6hkaYgVOM0QCA27407IIieZyTCIdpaqjfr0TuQ==

The conclusion I’m making is that WPT doesn’t interpret it properly. What is actually wrong with it?

The “Cache Static” check in WebPageTest is based on the presence of Cache-Control and Expires headers, and it is evaluating both the max-age as well as how long until the resource expires. Usually these are in sync, but in your your example, WebPageTest is seeing that an Expires header does not exist, and it believes that the resource was not cached. As you noted, this is a false positive and the browser is actually caching it.

“The Cache-Control header was defined as part of the HTTP/1.1 specification and supersedes previous headers (for example, Expires) used to define response caching policies. All modern browsers support Cache-Control, so that’s all you need.”

In other words, WPT should not check presence of Expires if cache-control is present.