A join_table usually contains at least 2 xx_id columns, meant as foreign_key columns of 2 other tables. When the join_table contains other extra columns, HABTM correctly ignores those columns and performs worker.skills << skill as INSERT INTO join_table (fk1_id, fk2_id) VALUES ...
However, if the join_table has its own id, HABTM gets confused and include the 'id' column into the INSERT with one of the fk id's value resulting in the sql INSERT INTO join_table (id, fk1_id, fk2_id) which is incorrect. Had HABTM continue to perform INSERT INTO join_table (fk1_id, fk2_id) VALUES ... it would've been correct.
Including extra columns in join_table shouldn't result in such drastic behavior differences?