Skip to content

Conversation

@DavisVaughan
Copy link
Member

Closes #2061

@MilesMcBain it turns out we already have these two useful FAQ pages:

Mimicking some ideas from the Rust compiler, we can link directly to these with cli from the error message

We now throw 3 distinct error messages - @lionel- and @hadley this is your chance to critique these

library(vctrs)

# Scalar
x <- expression()
obj_check_vector(x)
#> Error:
#> ! `x` must be a vector, not an expression vector.
#> ℹ Read our FAQ about scalar types (`?faq_error_scalar_type`) to learn more.

# S3 list
x <- structure(list(), class = "my_list")
obj_check_vector(x)
#> Error:
#> ! `x` must be a vector, not a <my_list> object.
#> ✖ Detected incompatible S3 list. To be a vector, the object must explicitly inherit from <list> or should implement a `vec_proxy()` method. Class: <my_list>.
#> ℹ If this object comes from a package, please report this error to the package author.
#> ℹ Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more.

# Incompatible data frame
x <- data_frame(a = 1)
class(x) <- c("data.frame", "my_df")
obj_check_vector(x)
#> Error:
#> ! `x` must be a vector, not a <data.frame> object.
#> ✖ Detected incompatible data frame subclass. To be a vector, the subclass must come before <data.frame> in the class, not after. Class: <data.frame/my_df>.
#> ℹ If this object comes from a package, please report this error to the package author.
#> ℹ Read our FAQ about creating vector types (`?howto_faq_fix_scalar_type_error`) to learn more.

Interactively, cli shows the links as clickable links

Screenshot 2025-10-09 at 10 00 02 AM

It's a bit annoying to improve on x must be a vector, not a <data.frame> object. without more work than I'm willing to put in, but I think the rest of the message clears up this edge case.

Comment on lines 44 to +45
#' @name howto-faq-fix-scalar-type-error
#' @aliases howto_faq_fix_scalar_type_error
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created underscored aliases for these for use in the cli bullet. In cli's fallback case it shows ?faq_error_scalar_type which doesn't work well with - if you try and copy and paste it in an R console. We've also learned this in the past with ?rlang::args_dots_empty

@DavisVaughan DavisVaughan requested a review from lionel- October 9, 2025 14:05
R/conditions.R Outdated
Comment on lines 682 to 690
message <- glue::glue("{arg} must be a vector, not {obj_type_friendly(x)}.")

if (needs_incompatible_s3_list_bullets(x)) {
message <- with_incompatible_s3_list_bullets(x, message)
} else if (needs_incompatible_data_frame_bullets(x)) {
message <- with_incompatible_data_frame_bullets(x, message)
} else {
message <- with_scalar_faq_bullet(message)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to write it like this, where the individual functions know if they're needed or not.

Suggested change
message <- glue::glue("{arg} must be a vector, not {obj_type_friendly(x)}.")
if (needs_incompatible_s3_list_bullets(x)) {
message <- with_incompatible_s3_list_bullets(x, message)
} else if (needs_incompatible_data_frame_bullets(x)) {
message <- with_incompatible_data_frame_bullets(x, message)
} else {
message <- with_scalar_faq_bullet(message)
}
message <- c(
glue::glue("{arg} must be a vector, not {obj_type_friendly(x)}."),
incompatible_s3_list_bullets(x),
incompatible_data_frame_bullets(x),
scalar_faq_bullet()
)

(probably tweaking the function names to make it clear they're only generated it needed)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea it's the last one that's the problem. I only want a scalar faq bullet if we don't have a more specific bullet to show first

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incompatible_s3_list_bullets(x) %||%
  incompatible_data_frame_bullets(x) %||%
  scalar_faq_bullet()

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that's pretty good

Copy link
Member

@lionel- lionel- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

R/conditions.R Outdated
Comment on lines 760 to 761
"Detected incompatible data frame subclass.",
"To be a vector, the subclass must come before {.cls data.frame} in the",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That message is a bit confusing to me. Maybe it's worth expanding a bit:

Suggested change
"Detected incompatible data frame subclass.",
"To be a vector, the subclass must come before {.cls data.frame} in the",
"Detected unexpected data frame structure.",
"A data frame is normally treated as vector but the detection was thrown off by an unexpected subclass ordering. To be compatible with vctrs, a data frame subclass must come before {.cls data.frame} in the",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think "incompatible" makes it seem like a valid structure, so "unexpected" is probably better

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've revised the data frame message in d4a7383 but I do think "incompatible" is still right. It's incompatible with vctrs. I don't want to mention vctrs in the error though, because this error could get thrown from any tidyverse function and the error_call won't mention a vctrs function.

What do you think of the new message?

@DavisVaughan DavisVaughan force-pushed the feature/better-scalar-error branch from fbd201f to f53db02 Compare October 21, 2025 17:50
@DavisVaughan DavisVaughan merged commit f0b048c into main Oct 21, 2025
13 checks passed
@DavisVaughan DavisVaughan deleted the feature/better-scalar-error branch October 21, 2025 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error messages regarding vector type check failures can be confusing

3 participants