diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 3e3efa3c3b..affdf06d0d 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -21079,3 +21079,8 @@ setindex(DT, b) # make sure that print(DT) doesn't warn due to the header missing index column types, #6806 # can't use output= here because the print() call is outside withCallingHandlers(...) test(2307, { capture.output(print(DT, class = TRUE, show.indices = TRUE)); TRUE }) + +# test for enhancing error message of invalid column #6512 +test(2308, { + melt(data.table(A = 1:5, B = 6:10), id.vars = c("A", "-1")) +}, error = "One or more values in 'id.vars' are invalid") diff --git a/src/fmelt.c b/src/fmelt.c index a778f48b78..e17536eacb 100644 --- a/src/fmelt.c +++ b/src/fmelt.c @@ -179,17 +179,30 @@ SEXP uniq_diff(SEXP int_or_list, int ncol, bool is_measure) { SEXP int_vec = PROTECT(isNewList(int_or_list) ? unlist_(int_or_list) : int_or_list); SEXP is_duplicated = PROTECT(duplicated(int_vec, FALSE)); int n_unique_cols = 0; - for (int i=0; i 0 && col_number <= ncol); if (is_measure) good_number |= (col_number==NA_INTEGER); if (!good_number) { - if (is_measure) { - error(_("One or more values in 'measure.vars' is invalid.")); - } else { - error(_("One or more values in 'id.vars' is invalid.")); - } - } else if (!LOGICAL(is_duplicated)[i]) n_unique_cols++; + invalid_col_ptr[invalid_count++] = col_number; + } else if (!LOGICAL(is_duplicated)[i]) { + n_unique_cols++; + } + } + if (invalid_count > 0) { + char buffer[4096] = "", *nexti = buffer; + size_t remaining = sizeof buffer; + for (int i = 0; i < invalid_count; ++i) { + int offset = snprintf(nexti, remaining, "%s[%d]", i > 0 ? ", " : "", invalid_col_ptr[i]); + if (offset < 0 || (size_t)offset >= remaining) break; + nexti += offset; + remaining -= offset; + } + error(_("One or more values in '%s' are invalid; please fix by removing: %s"), + is_measure ? "measure.vars" : "id.vars", buffer); } SEXP unique_col_numbers = PROTECT(allocVector(INTSXP, n_unique_cols)); int unique_i = 0; @@ -199,7 +212,7 @@ SEXP uniq_diff(SEXP int_or_list, int ncol, bool is_measure) { } } SEXP out = set_diff(unique_col_numbers, ncol); - UNPROTECT(3); + UNPROTECT(4); return out; }